下面咱們看看用scrapy模擬登陸的基本寫法:html
注意:咱們常常調試代碼的時候基本都用chrome瀏覽器,可是我就由於用了谷歌瀏覽器(它老是登陸的時候不提示我用驗證碼,誤導我覺得登陸時不須要驗證碼,其實登陸時候必需要驗證碼的),這裏你能夠多試試幾個瀏覽器,必定要找個提示你輸入驗證碼的瀏覽器調試。python
一、咱們登陸的時候,提示咱們輸入驗證碼,當驗證碼彈出以前會有個請求,咱們打開這個請求,很明顯,type是login,驗證碼無疑了,就算是看請求的由於名,你也應該知道這個就是驗證碼的請求,或者打開這個驗證碼的請求url,這。chrome
驗證碼的圖片,悲慘了,這怎麼整。彆着急。。json
二、驗證碼提示咱們要點擊倒着寫的字體,這。。。,爬蟲和反爬蟲就是無休止的互相折磨。這明顯就是上面那個圖片的信息。瀏覽器
三、機智的我,發現驗證碼的請求參數裏面有三個參數,r是一個13位的數字,type是登陸用的,lang很可疑,改改它,把cn給他改爲en。mygod這不也是驗證碼麼,就試試它了。dom
四、頁面基本登陸原理分析完了,咱們接下來看看代碼怎麼寫,首先咱們重構scrapy的start_requests方法(有scrapy基礎的同窗都知道,這個名字可不是瞎寫的)。scrapy
五、分析這個驗證碼的請求鏈接,https://www.zhihu.com/captcha.gif?r=1511878790500&type=login&lang=en,這裏面均可以固定,可是這個驗證碼確定不行,13位的數字,果斷想到了當前時間ide
最後,咱們要請求這個url,這裏必需要加上請求頭信息,callback就是下面你要執行的方法。post
def start_requests(self): ''' 一、首先構造並抓取登陸須要提交的驗證碼 :return: ''' t = str(int(time.time() * 1000)) captcha_url = 'https://www.zhihu.com/captcha.gif?r={0}&type=login&lang=en'.format(t) return [scrapy.Request(url=captcha_url, headers=self.header, callback=self.parser_captcha)]
六、上面請求完成後,就會將請求結果直接返回個下面的這個方法,因此它必須有個形式參數,來接收請求的結果,首先咱們將請求的的結果,其實就是剛纔咱們看到的那個圖片,圖片的信息就在body裏面,直接將整個body存成一個文件,而後我這裏用的是Image打開咱們存入的文件,文件都給你打開了,你還不得看看輸入一下(若是你有云大碼平臺的服務,就直接讓雲大碼平臺搞定就行),這裏咱們只能本身看本身輸入了。搞完了驗證碼,咱們如今準備開始登錄,這裏可不是直接用登錄的url登錄就行,你仔細的話還有個xrsf參數須要咱們獲取,那就請求的url直接就是登錄頁面,注意你的頭部信息,不假裝一下,立馬給你請求出錯。callback就不說了吧。這須要注意的就是,這直接把驗證碼存入了scrapy的meta裏面了。字體
def parser_captcha(self, response): ''' 一、根據start_requests方法返回的驗證碼,將它存入本地 二、打開下載下來的驗證碼 三、這裏是須要手動輸入的,這裏能夠接入打碼平臺 :param response: :return: ''' with open('captcha.jpg', 'wb') as f: f.write(response.body) f.close() try: im = Image.open('captcha.jpg') im.show() im.close() except: pass captcha = input("請輸入你的驗證>") return scrapy.FormRequest(url='https://www.zhihu.com/#signin', headers=self.header, callback=self.login, meta={ 'captcha': captcha })
七、下面咱們來搞定xsrf參數,這裏我用xpath,一句話搞定,下面就是post_url就是上面phone_num請求裏面的url,也是真正意義上的post提交登陸信息的url。由於咱們已經把驗證碼放進了meta裏面了,因此這裏直接獲取就行。基本登陸信息假裝完成之後,開始提交登陸信息,登陸完成之後,咱們設置一個callback回調方法,檢查一下登陸信息。
def login(self, response): xsrf = response.xpath("//input[@name='_xsrf']/@value").extract_first() if xsrf is None: return '' post_url = 'https://www.zhihu.com/login/phone_num' post_data = { "_xsrf": xsrf, "phone_num": '你的帳戶名稱', "password": '你的帳戶密碼', "captcha": response.meta['captcha'] } return [scrapy.FormRequest(url=post_url, formdata=post_data, headers=self.header, callback=self.check_login)]
八、上面請求完成之後,會返回咱們一個字典,這裏咱們判斷一下是否登陸成功,若是登陸成功之後,就執行咱們start_urls裏面的url地址,由於已經登陸成功了,因此這裏咱們的start_urls就是https://www.zhihu.com,這樣咱們就能夠再parse方法裏面繼續解析咱們登陸後的html信息了。
def check_login(self, response): js = json.loads(response.text) print(js) if 'msg' in js and js['msg'] == '登陸成功': for url in self.start_urls: print(url) yield scrapy.Request(url=url, headers=self.header, dont_filter=True) else: print("登陸失敗,請檢查!!!")
代碼以下:
import json import scrapy import time from PIL import Image class ZhihuloginSpider(scrapy.Spider): name = 'zhihu_login' allowed_domains = ['zhihu.com'] start_urls = ['https://www.zhihu.com/'] header = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML,' ' like Gecko) Chrome/62.0.3202.94 Safari/537.36', } def parse(self, response): #主頁爬取的具體內容 print(response.text) def start_requests(self): ''' 一、首先構造並抓取登陸須要提交的驗證碼 :return: ''' t = str(int(time.time() * 1000)) captcha_url = 'https://www.zhihu.com/captcha.gif?r={0}&type=login&lang=en'.format(t) return [scrapy.Request(url=captcha_url, headers=self.header, callback=self.parser_captcha)] def parser_captcha(self, response): ''' 一、根據start_requests方法返回的驗證碼,將它存入本地 二、打開下載下來的驗證碼 三、這裏是須要手動輸入的,這裏能夠接入打碼平臺 :param response: :return: ''' with open('captcha.jpg', 'wb') as f: f.write(response.body) f.close() try: im = Image.open('captcha.jpg') im.show() im.close() except: pass captcha = input("請輸入你的驗證>") return scrapy.FormRequest(url='https://www.zhihu.com/#signin', headers=self.header, callback=self.login, meta={ 'captcha': captcha }) def login(self, response): xsrf = response.xpath("//input[@name='_xsrf']/@value").extract_first() if xsrf is None: return '' post_url = 'https://www.zhihu.com/login/phone_num' post_data = { "_xsrf": xsrf, "phone_num": '你的帳戶名稱', "password": '你的帳戶密碼', "captcha": response.meta['captcha'] } return [scrapy.FormRequest(url=post_url, formdata=post_data, headers=self.header, callback=self.check_login)] # 驗證返回是否成功 def check_login(self, response): js = json.loads(response.text) print(js) if 'msg' in js and js['msg'] == '登陸成功': for url in self.start_urls: print(url) yield scrapy.Request(url=url, headers=self.header, dont_filter=True) else: print("登陸失敗,請檢查!!!")