python爬蟲scrapy之登陸知乎

下面咱們看看用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("登陸失敗,請檢查!!!")
相關文章
相關標籤/搜索