Scrapy模擬登陸知乎

知乎新版登陸已經(jīng)增加了驗(yàn)證碼,此文章不再適用

感謝簡(jiǎn)書作者Andrew_liu提供的思路,雖然知乎改版后古程,該文章上提供的方法已經(jīng)失效Python爬蟲(七)--Scrapy模擬登錄

利用Scrapy提供的cookie中間價(jià)很容易做到網(wǎng)頁的模擬登陸,下面就來介紹怎么利用這個(gè)cookie中間件來登陸知乎礁鲁。

###****前期分析工作

  • 打開https://www.zhihu.com,利用Chrome瀏覽器的Debug功能待侵,定位到登陸框所在的位置陌选,如下圖所示


    利用scrapy提供的xpath能很方便的獲取到這個(gè)值(//div[@data-za-module="SignInForm"]//form//input[@name="_xsrf"]/@value')

  • 選中Debug窗口的Network選項(xiàng)替蔬,同時(shí)在輸完賬號(hào)密碼后點(diǎn)擊登陸厨幻,獲取登陸操作后的post請(qǐng)求相嵌,見下圖:

注意:由于知乎頁面在登錄成功后會(huì)跳轉(zhuǎn)到新的頁面,所以使用debug中的 >network功能獲取數(shù)據(jù)包時(shí)一定要在登錄后快速的將recording按鈕停止掉(上圖左上角那個(gè)黑色的圓圈按鈕,recoding狀態(tài)時(shí)紅色,黑色是stop recording狀態(tài))况脆,否則登錄的報(bào)文就沒了饭宾。

點(diǎn)擊這個(gè)鏈接,確認(rèn)這個(gè)鏈接就是提交登陸的url


從FormData里面可以看到https://www.zhihu.com/email/login就是登陸POST請(qǐng)求的url格了,需要提交4個(gè)參數(shù)看铆,其中_xsrf就是首頁可以獲取到的隱藏表單參數(shù),remember_me是是否記住cookie的開關(guān)盛末,email和password對(duì)應(yīng)賬號(hào)和密碼

此處可能有不一樣的地方弹惦,因?yàn)槲业闹踬~號(hào)是email注冊(cè)的,根據(jù)這個(gè)url的特征推測(cè)別的賬號(hào)類型可能存在不一樣的Url

### ****編寫蜘蛛代碼
1.繼承CrawlSpider,并重寫spider的start_request方法悄但,讓spier先訪問登錄頁再去爬取start_urls中的鏈接棠隐,在start_requests方法中,讓spider先去訪問知乎首頁檐嚣,去獲取隱藏的表單項(xiàng)_xsrf

def start_requests(self):
        return [Request("https://www.zhihu.com/",headers = self.headers,meta={"cookiejar":1},callback=self.post_login)]

其中header需要自定義助泽,因?yàn)橹鯇?duì)spider做了限制,應(yīng)該是檢測(cè)User-Agent,你可以在setting.py中更改spider的默認(rèn)UserAgent,也可以像我這樣自己自定義一個(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"
}

meta中的cookiejar是Scrapy的Cookie中間件的關(guān)鍵字嗡贺,具體可參考scrapy文檔隐解,這里因?yàn)橹恍枰4嬉粋€(gè)cookie,所以直接寫1(注意:并不是1個(gè)cookie才寫的1诫睬,僅僅是個(gè)key厢漩,后面通過這個(gè)1這個(gè)key找到cookiejar中保存的cookie)

2.解析首頁內(nèi)容,獲取到_xsrf的值岩臣,同時(shí)提交登錄請(qǐng)求:

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':1},
                                          headers = self.headers,
                                          formdata = {
                                             '_xsrf':xsrf,
                                             'password':'xxxxxxx',
                                             'email':'xxx@gmail.com',
                                             'remember_me':'true',
                                          },
                                          callback = self.after_login,
                                          )
  1. 將登錄成功后獲取到的cookie傳遞給每一個(gè)start_urls中鏈接的ruquest
def after_login(self,response):
        for url in self.start_urls:
            yield Request(url,meta={'cookiejar':1},headers = self.headers)

4.由于cookiejar中的cookie并不會(huì)自動(dòng)發(fā)送給每個(gè)鏈接,因此在urls通過Rule獲取到的連接宵膨,也是需要我們手動(dòng)將cookie加上架谎,通過Rule提供的process_request參數(shù)重新創(chuàng)建帶cookie的Request

rules = (
        Rule(SgmlLinkExtractor(allow=('/question/\\d*')),process_request="request_question"),
    )

同時(shí)提供request_question函數(shù)

def request_question(self,request):
        return Request(request.url,meta={'cookiejar':1},headers = self.headers,callback=self.parse_question)

5.由于已經(jīng)有了process_link ,Rule中的callback參數(shù)就不再起作用了,而是調(diào)用新構(gòu)造的Request中的callback函數(shù)辟躏。

def parse_question(self,response):
        sel = Selector(response)
        item = zhihuItem()
        item['qestionTitle'] = sel.xpath("http://div[@id='zh-question-title']//h2/text()").extract_first()
        item['image_urls'] = sel.xpath("http://img[@class='origin_image zh-lightbox-thumb lazy']/@data-original").extract()
        return item

這個(gè)parse_question方法僅僅是獲取問題名稱和問題下面的所有圖片鏈接谷扣。

### ****完整代碼

import urllib2
import os
import re
import codecs

from scrapy.contrib.spiders import CrawlSpider,Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.selector import Selector
from MySpider.items import zhihuItem
from scrapy.http import Request
from scrapy.http import FormRequest
from scrapy.utils.response import open_in_browser

class zhihuSpider(CrawlSpider):
    name = "zhihu"
    allow_domians = ["zhihu.com"]
    start_urls = ["https://www.zhihu.com/collection/38624707"]
    rules = (
        Rule(SgmlLinkExtractor(allow=('/question/\\d*')),process_request="request_question"),
    )
    
    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"
    }
    
    def start_requests(self):
        return [Request("https://www.zhihu.com/",headers = self.headers,meta={"cookiejar":1},callback=self.post_login)]
        
    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':'差點(diǎn)就忘了刪了',
                                             'email':'郵箱也不能暴露',
                                             'remember_me':'true',
                                          },
                                          callback = self.after_login,
                                          )
                                                      
    def after_login(self,response):
        for url in self.start_urls:
            yield Request(url,meta={'cookiejar':1},headers = self.headers)
   
    def request_question(self,request):
        return Request(request.url,meta={'cookiejar':1},headers = self.headers,callback=self.parse_question)
        
    def parse_question(self,response):
        sel = Selector(response)
        item = zhihuItem()
        item['qestionTitle'] = sel.xpath("http://div[@id='zh-question-title']//h2/text()").extract_first()
        item['image_urls'] = sel.xpath("http://img[@class='origin_image zh-lightbox-thumb lazy']/@data-original").extract()
        return item
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市捎琐,隨后出現(xiàn)的幾起案子会涎,更是在濱河造成了極大的恐慌,老刑警劉巖瑞凑,帶你破解...
    沈念sama閱讀 216,402評(píng)論 6 499
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件末秃,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡籽御,警方通過查閱死者的電腦和手機(jī)练慕,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,377評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來技掏,“玉大人铃将,你說我怎么就攤上這事⊙剖幔” “怎么了劲阎?”我有些...
    開封第一講書人閱讀 162,483評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)鸠真。 經(jīng)常有香客問我悯仙,道長(zhǎng),這世上最難降的妖魔是什么弧哎? 我笑而不...
    開封第一講書人閱讀 58,165評(píng)論 1 292
  • 正文 為了忘掉前任雁比,我火速辦了婚禮,結(jié)果婚禮上撤嫩,老公的妹妹穿的比我還像新娘偎捎。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,176評(píng)論 6 388
  • 文/花漫 我一把揭開白布茴她。 她就那樣靜靜地躺著寻拂,像睡著了一般。 火紅的嫁衣襯著肌膚如雪丈牢。 梳的紋絲不亂的頭發(fā)上祭钉,一...
    開封第一講書人閱讀 51,146評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音己沛,去河邊找鬼慌核。 笑死,一個(gè)胖子當(dāng)著我的面吹牛申尼,可吹牛的內(nèi)容都是我干的垮卓。 我是一名探鬼主播,決...
    沈念sama閱讀 40,032評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開眼师幕,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼粟按!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起霹粥,我...
    開封第一講書人閱讀 38,896評(píng)論 0 274
  • 序言:老撾萬榮一對(duì)情侶失蹤灭将,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后后控,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庙曙,經(jīng)...
    沈念sama閱讀 45,311評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,536評(píng)論 2 332
  • 正文 我和宋清朗相戀三年浩淘,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了矾利。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,696評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡馋袜,死狀恐怖男旗,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情欣鳖,我是刑警寧澤察皇,帶...
    沈念sama閱讀 35,413評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站泽台,受9級(jí)特大地震影響什荣,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜怀酷,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,008評(píng)論 3 325
  • 文/蒙蒙 一稻爬、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧蜕依,春花似錦桅锄、人聲如沸琉雳。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽翠肘。三九已至,卻和暖如春辫秧,著一層夾襖步出監(jiān)牢的瞬間束倍,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,815評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工盟戏, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留绪妹,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 47,698評(píng)論 2 368
  • 正文 我出身青樓柿究,卻偏偏與公主長(zhǎng)得像喂急,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子笛求,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,592評(píng)論 2 353

推薦閱讀更多精彩內(nèi)容