scrapy模擬登陸知乎--抓取熱點(diǎn)話題

工具準(zhǔn)備

在開(kāi)始之前,請(qǐng)確保scrpay正確安裝,手頭有一款簡(jiǎn)潔而強(qiáng)大的瀏覽器, 若是你有使用postman那就更好了。

scrapy genspider zhihu

使用以上命令生成知乎爬蟲(chóng),代碼如下:

# -*- coding: utf-8 -*-import scrapyclassZhihuSpider(scrapy.Spider):? ? name ='zhihu'? ? allowed_domains = ['www.zhihu.com']? ? start_urls = ['http://www.zhihu.com/']defparse(self, response):pass

有一點(diǎn)切記,不要忘了啟用Cookies,切記切記

# Disable cookies (enabled by default)COOKIES_ENABLED =True

模擬登陸

過(guò)程如下:

進(jìn)入登錄頁(yè),獲取HeaderCookie信息,

完善的Header信息能盡量偽裝爬蟲(chóng), 有效Cookie信息能迷惑知乎服務(wù)端,使其認(rèn)為當(dāng)前登錄非首次登錄,若無(wú)有效Cookie會(huì)遭遇驗(yàn)證碼。 在抓取數(shù)據(jù)之前,請(qǐng)?jiān)跒g覽器中登錄過(guò)知乎,這樣才使得Cookie是有效的。

歡迎加入我的QQ群`923414804`與我一起學(xué)習(xí),群里有我學(xué)習(xí)過(guò)程中整理的大量學(xué)習(xí)資料。加群即可免費(fèi)獲取

HeaderCookie整理如下:

headers = {'Host':'www.zhihu.com','Connection':'keep-alive','Origin':'https://www.zhihu.com','User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.90 Safari/537.36','Content-Type':'application/x-www-form-urlencoded; charset=UTF-8','Accept':'*/*','X-Requested-With':'XMLHttpRequest','DNT':1,'Referer':'https://www.zhihu.com/','Accept-Encoding':'gzip, deflate, br','Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6',}cookies = {'d_c0':'"AHCAtu1iqAmPTped76X1ZdN0X_qAwhjdLUU=|1458699045"','__utma':'51854390.1407411155.1458699046.1458699046.1458699046.1','__utmv':'51854390.000--|3=entry_date=20160322=1','_zap':'850897bb-cba4-4d0b-8653-fd65e7578ac2','q_c1':'b7918ff9a5514d2981c30050c8c732e1|1502937247000|1491446589000','aliyungf_tc':'AQAAAHVgviiNyQsAOhSntJ5J/coWYtad','_xsrf':'b12fdca8-cb35-407a-bc4c-6b05feff37cb','l_cap_id':'"MDk0MzRjYjM4NjAwNDU0MzhlYWNlODQ3MGQzZWM0YWU=|1503382513|9af99534aa22d5db92c7f58b45f3f3c772675fed"','r_cap_id':'"M2RlNDZjN2RkNTBmNGFmNDk2ZjY4NjIzY2FmNTE4NDg=|1503382513|13370a99ee367273b71d877de17f05b2986ce0ef"','cap_id':'"NmZjODUxZjQ0NzgxNGEzNmJiOTJhOTlkMTVjNWIxMDQ=|1503382513|dba2e9c6af7f950547474f827ef440d7a2950163"',

}

在瀏覽器中,模擬登陸,抓取登陸請(qǐng)求信息。

從圖中可以看到_xsrf參數(shù), 這個(gè)參數(shù)與登陸驗(yàn)證信息無(wú)關(guān),但很明顯是由登陸頁(yè)面攜帶的信息。Google了下xsrf的含義, 用于防范跨站請(qǐng)求偽造。


整理以上,代碼如下:

loginUrl ='https://www.zhihu.com/#signin'siginUrl ='https://www.zhihu.com/login/email'defstart_requests(self):return [? ? ? ? scrapy.http.FormRequest(? ? ? ? ? ? self.loginUrl,? ? ? ? ? ? headers=self.headers,? ? ? ? ? ? cookies=self.cookies,? ? ? ? ? ? meta={'cookiejar':1},? ? ? ? ? ? callback=self.post_login)? ? ]defpost_login(self, response):? ? xsrf = response.css('div.view-signin > form > input[name=_xsrf]::attr(value)'? ? ).extract_first()? ? self.headers['X-Xsrftoken'] = xsrfreturn [? ? ? ? scrapy.http.FormRequest(? ? ? ? ? ? self.siginUrl,? ? ? ? ? ? method='POST',? ? ? ? ? ? headers=self.headers,? ? ? ? ? ? meta={'cookiejar': response.meta['cookiejar']},? ? ? ? ? ? formdata={'_xsrf': xsrf,'captcha_type':'cn','email':'xxxxxx@163.com','password':'xxxxxx',

? ? ? ? ? ? },

? ? ? ? ? ? callback=self.after_login)

? ? ]

設(shè)置Bearer Token

經(jīng)過(guò)上述步驟登陸成功了,有點(diǎn)小激動(dòng),有沒(méi)有! 但苦難到此還遠(yuǎn)沒(méi)有結(jié)束,這個(gè)時(shí)候嘗試抓取最近熱門話題,直接返回code:401,未授權(quán)的訪問(wèn)。 授權(quán)信息未設(shè)置,導(dǎo)致了此類錯(cuò)誤,莫非遺漏了什么,看來(lái)只能在瀏覽器中追蹤請(qǐng)求參數(shù)來(lái)偵測(cè)問(wèn)題。 在瀏覽器的請(qǐng)求中,包含了Bearer Token, 而我在scrapy中模擬的請(qǐng)求中未包含此信息, 所以我被服務(wù)器認(rèn)定為未授權(quán)的。 通過(guò)觀察發(fā)現(xiàn)Bearer Token的關(guān)鍵部分,就是Cookies中的z_c0包含的信息。


z_c0包含的信息,是在登陸完成時(shí)種下的,所以從登陸完成返回的登陸信息里,獲取要設(shè)置的Cookie信息, 然后拼接出Bearer Token,最后設(shè)置到Header中。

代碼整理如下:

defafter_login(self, response):? ? jdict = json.loads(response.body)? ? print('after_login', jdict)if jdict['r'] ==0:? ? ? ? z_c0 = response.headers.getlist('Set-Cookie')[2].split(';')[0].split('=')[1]? ? ? ? self.headers['authorization'] ='Bearer ' + z_c0return scrapy.http.FormRequest(? ? ? ? ? ? url=self.feedUrl,? ? ? ? ? ? method='GET',? ? ? ? ? ? meta={'cookiejar': response.meta['cookiejar']},? ? ? ? ? ? headers=self.headers,? ? ? ? ? ? formdata={'action_feed':'True','limit':'10','action':'down','after_id': str(self.curFeedId),'desktop':'true'? ? ? ? ? ? },? ? ? ? ? ? callback=self.parse)else:? ? ? ? print(jdict['error'])

獲取數(shù)據(jù)

上述步驟后,數(shù)據(jù)獲取就水到渠成了,為了檢測(cè)成功與否, 把返回信息寫(xiě)到文件中,而且只獲取前五十個(gè),代碼如下:

feedUrl ='https://www.zhihu.com/api/v3/feed/topstory'nextFeedUrl =''curFeedId =0defparse(self, response):with open('zhihu.json','a')as fd:? ? ? ? fd.write(response.body)? ? jdict = json.loads(response.body)? ? jdatas = jdict['data']for entryin jdatas:? ? ? ? entry['pid'] = entry['id']yield entry? ? jpaging = jdict['paging']? ? self.curFeedId += len(jdatas)if jpaging['is_end'] ==Falseand self.curFeedId <50:? ? ? ? self.nextFeedUrl = jpaging['next']yield self.next_request(response)defnext_request(self, response):return scrapy.http.FormRequest(? ? ? ? url=self.nextFeedUrl,? ? ? ? method='GET',? ? ? ? meta={'cookiejar': response.meta['cookiejar']},

? ? ? ? headers=self.headers,

? ? ? ? callback=self.parse)

最終獲取的數(shù)據(jù)如下圖所示:

寫(xiě)在最后

知乎的數(shù)據(jù),只有登錄完成之后,才可有效的獲取,所以模擬登陸是無(wú)法忽略不管的。 所謂的模擬登陸,只是在scrapy中盡量的模擬在瀏覽器中的交互過(guò)程,使服務(wù)端無(wú)感抓包過(guò)程。 請(qǐng)求中附加有效的CookiesHeaders頭信息,可有效的迷惑服務(wù)端, 同時(shí)在交互的過(guò)程中,獲取后續(xù)請(qǐng)求必要信息和認(rèn)證信息,使得整個(gè)流程能不斷先前。

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書(shū)系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容