最近學(xué)習(xí)Python爬蟲,用到了Scrapy這個(gè)爬蟲框架。目前Scrapy的最新版本已經(jīng)達(dá)到了Scrapy 1.4,并且支持Python 3,但是網(wǎng)上找到的中文資料基本都是老版本的Scrapy,并且只支持到Python 2.7。于是筆者決定將Scrapy 1.4的學(xué)習(xí)過(guò)程記錄下來(lái),供各位童鞋參考。
這篇文章講解了如何模擬登陸知乎,參考另一篇簡(jiǎn)書文章Scrapy模擬登陸知乎,不過(guò)這篇文章是基于Python 2.7的版本,細(xì)節(jié)方面沒(méi)弄清楚的童鞋可以去看看原文章。
模擬登陸過(guò)程都是在Spider類中完成的,這里用最基本的Spider實(shí)現(xiàn)。
1.在spiders目錄下創(chuàng)建一個(gè)py文件:zhihu_spider.py,繼承自Spider,先把基本的一些東西寫進(jìn)去:
class ZhihuQuestionSpider(Spider):
? ? url_base = 'https://www.zhihu.com'? # 供后面獲取鏈接使用
? ? name = 'login'? # Spider的名字
? ? start_url_base = 'https://www.zhihu.com/collection/27915947?page='? # 爬取頁(yè)面
? ? start_urls = ['https://www.zhihu.com/collection/27915947']? # 這里沒(méi)用到這個(gè)
? ? headers = {
? ? ? ? "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
? ? ? ? "Accept-Encoding": "gzip,deflate",
? ? ? ? "Accept-Language": "en-US,en;q=0.8,zh-TW;q=0.6,zh;q=0.4",
? ? ? ? "Connection": "keep-alive",
? ? ? ? "Content-Type": " application/x-www-form-urlencoded; charset=UTF-8",
? ? ? ? "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.97 Safari/537.36",
? ? ? ? "Referer": "http://www.zhihu.com"
? ? }
里面都是一些之后會(huì)用到的量,注釋講的很清楚了。
2.重寫Spider的start_requests方法。
這里是整個(gè)爬蟲的開始,從知乎首頁(yè)開始,模擬登陸環(huán)境,這里的cookiejar是Scrapy的Cookie中間件的關(guān)鍵字,1表示這里只需要保存一個(gè)Cookie。這個(gè)方法將獲取到的頁(yè)面交給post_login方法模擬登陸。
# 從這里開始↓
def start_requests(self):
? ? return [Request("https://www.zhihu.com/", headers=self.headers, meta={"cookiejar": 1}, callback=self.post_login)]
3.post_login模擬登陸方法。注意修改一下登陸郵箱和密碼。
# 進(jìn)入知乎主頁(yè)模仿登陸
def post_login(self, response):
? ? self.log('preparing login...')
? ? xsrf = Selector(response).xpath('//div[@data-za-module="SignInForm"]//form//input[@name="_xsrf"]/@value').extract()[0]
? ? self.log(xsrf)
? ? return FormRequest("https://www.zhihu.com/login/email", meta={'cookiejar': response.meta['cookiejar']},
? ? ? ? headers=self.headers,
? ? ? ? formdata={
? ? ? ? '_xsrf': xsrf,
? ? ? ? 'password': '不能把密碼告訴你們',
? ? ? ? 'email': '郵箱也不行',
? ? ? ? 'remember_me': 'true',
? ? ? ? },
? ? ? ? callback=self.after_login,
? ? )
4.登陸成功后的爬蟲操作。這里先介紹以下這個(gè)案例的爬蟲行為:
首先是最開始爬取的頁(yè)面:這是一個(gè)名為生活文體藝術(shù)見聞的收藏,共有九百多篇收藏。
從這個(gè)頁(yè)面獲取每個(gè)提問(wèn)的頁(yè)面,在從提問(wèn)頁(yè)面里獲取問(wèn)題、鏈接、閱讀量、關(guān)注量等信息,如下圖中紅圈圈出來(lái)的信息。
這里有個(gè)問(wèn)題,收藏頁(yè)面只顯示10個(gè)提問(wèn),剩下的提問(wèn)在分頁(yè)里面,怎么處理呢?
可以通過(guò)這個(gè)鏈接搞定:
start_url_base = 'https://www.zhihu.com/collection/27915947?page='? # 爬取頁(yè)面
page=后面填入相應(yīng)的數(shù)字就代表相應(yīng)的分頁(yè),當(dāng)我們將第一個(gè)分頁(yè)的提問(wèn)爬取完成之后,將這個(gè)url后面加入其他的數(shù)字就可以爬取下一頁(yè)的提問(wèn)了。
5.登陸成功后進(jìn)入相應(yīng)的分頁(yè)(即每頁(yè)顯示十個(gè)提問(wèn)的那個(gè)頁(yè)面),這個(gè)收藏一共91頁(yè),所以循環(huán)(1~91)次。
# 登陸成功后從start_urls里讀出初始url,注入cookie
def after_login(self,response):
? ? # 創(chuàng)建csv文件
? ? with open('items.csv', 'w', newline='') as csvfile:
? ? writer = csv.writer(csvfile, dialect=('excel'))
? ? writer.writerow(['標(biāo)題', '鏈接', '關(guān)注量', '瀏覽量'])
? ? for page in range(1, 92):
? ? ? ? url = self.start_url_base + str(page)
? ? ? ? yield Request(url, meta={'cookiejar': 1}, headers=self.headers, callback=self.request_question)
6.分析該分頁(yè),得到提問(wèn)的鏈接,并進(jìn)入提問(wèn)頁(yè)面爬取有用的信息。筆者還是更喜歡用BeautifulSoup,將xpath轉(zhuǎn)為BeautifulSoup可以這樣:
soup = BeautifulSoup(request.body, 'lxml')
# 分析得到urls
def request_question(self,request):
? ? soup = BeautifulSoup(request.body, 'lxml')
? ? for urlDiv in soup.find_all('div', class_='zm-item'):
? ? ? ? url = self.url_base + urlDiv.find('a').get('href')
? ? ? ? yield Request(url,meta={'cookiejar':1},headers = self.headers,callback=self.parse_question)
7.最后一步了,進(jìn)入提問(wèn)頁(yè)面,提取有用信息保存到csv中。
# 獲取有用的信息
def parse_question(self,response):
? ? soup = BeautifulSoup(response.body, 'lxml')
? ? item = ZhihuItem()
? ? item['questionTitle'] = soup.find('h1').string
? ? item['url'] = response.url
? ? followDiv = soup.find('div', class_='NumberBoard QuestionFollowStatus-counts')
? ? item['follow'] = followDiv.find_all('div', class_='NumberBoard-value')[0].string
? ? item['page_view'] = followDiv.find_all('div', class_='NumberBoard-value')[1].string
? ? # 將問(wèn)題標(biāo)題寫入csv
? ? with open('items.csv', 'a', newline='') as csvfile:
? ? ? ? writer = csv.writer(csvfile, dialect=('excel'))
? ? ? ? writer.writerow([item['questionTitle'], item['url'], item['follow'], item['page_view']])
? ? return item
8.在命令行里輸入:scrapy crawl login運(yùn)行爬蟲,爬取結(jié)果如下:
不過(guò)沒(méi)能解決知乎安全驗(yàn)證的問(wèn)題,當(dāng)爬取過(guò)多、過(guò)快時(shí)就要輸入驗(yàn)證碼了。
(PS.誰(shuí)能告訴簡(jiǎn)書怎么插入代碼啊,```完全沒(méi)用呀?。。。?br>