python爬蟲scrapy之登錄知乎


下面我們看看用scrapy模擬登錄的基本寫法:

  注意:我們經常調試代碼的時候基本都用chrome瀏覽器,但是我就因為用了谷歌瀏覽器(它總是登錄的時候不提示我用驗證碼,誤導我以為登錄時不需要驗證碼,其實登錄時候必須要驗證碼的),這里你可以多試試幾個瀏覽器,一定要找個提示你輸入驗證碼的瀏覽器調試。

  1、我們登錄的時候,提示我們輸入驗證碼,當驗證碼彈出之前會有個請求,我們打開這個請求,很明顯,type是login,驗證碼無疑了,就算是看請求的因為名,你也應該知道這個就是驗證碼的請求,或者打開這個驗證碼的請求url,這。

  

  

  驗證碼的圖片,悲慘了,這怎么整。別着急。。

  

  2、驗證碼提示我們要點擊倒着寫的字體,這。。。,爬蟲和反爬蟲就是無休止的互相折磨。這明顯就是上面那個圖片的信息。

  

  3、機智的我,發現驗證碼的請求參數里面有三個參數,r是一個13位的數字,type是登錄用的,lang很可疑,改改它,把cn給他改成en。mygod這不也是驗證碼么,就試試它了。

  

  

  4、頁面基本登錄原理分析完了,我們接下來看看代碼怎么寫,首先我們重構scrapy的start_requests方法(有scrapy基礎的同學都知道,這個名字可不是瞎寫的)。

  5、分析這個驗證碼的請求連接,https://www.zhihu.com/captcha.gif?r=1511878790500&type=login&lang=en,這里面都可以固定,但是這個驗證碼肯定不行,13位的數字,果斷想到了當前時間

   最后,我們要請求這個url,這里必須要加上請求頭信息,callback就是下面你要執行的方法。

    def start_requests(self):
        '''
        1、首先構造並抓取登錄需要提交的驗證碼
        :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)]

  6、上面請求完成后,就會將請求結果直接返回個下面的這個方法,所以它必須有個形式參數,來接收請求的結果,首先我們將請求的的結果,其實就是剛才我們看到的那個圖片,圖片的信息就在body里面,直接將整個body存成一個文件,然后我這里用的是Image打開我們存入的文件,文件都給你打開了,你還不得看看輸入一下(如果你有雲大碼平台的服務,就直接讓雲大碼平台搞定就行),這里我們只能自己看自己輸入了。搞完了驗證碼,我們現在准備開始登陸,這里可不是直接用登陸的url登陸就行,你仔細的話還有個xrsf參數需要我們獲取,那就請求的url直接就是登陸頁面,注意你的頭部信息,不偽裝一下,立馬給你請求出錯。callback就不說了吧。這需要注意的就是,這直接把驗證碼存入了scrapy的meta里面了。

    def parser_captcha(self, response):
        '''
        1、根據start_requests方法返回的驗證碼,將它存入本地
        2、打開下載下來的驗證碼
        3、這里是需要手動輸入的,這里可以接入打碼平台
        :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
        })

  7、下面我們來搞定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)]

  8、上面請求完成以后,會返回我們一個字典,這里我們判斷一下是否登錄成功,如果登錄成功以后,就執行我們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):
        '''
        1、首先構造並抓取登錄需要提交的驗證碼
        :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):
        '''
        1、根據start_requests方法返回的驗證碼,將它存入本地
        2、打開下載下來的驗證碼
        3、這里是需要手動輸入的,這里可以接入打碼平台
        :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("登錄失敗,請檢查!!!")

  


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM