1. 程式人生 > >菜鳥寫Python實戰:Scrapy完成知乎登入並儲存cookies檔案用於請求他頁面(by Selenium)

菜鳥寫Python實戰:Scrapy完成知乎登入並儲存cookies檔案用於請求他頁面(by Selenium)

一、前言

現在知乎的登入請求越來越複雜了,通過f12調出瀏覽器網路請求情況分析request引數,似乎不再簡單可知了,因為知乎很多請求引數都字元加密顯示了,如下圖,我們很難再知道發起請求時要傳遞什麼引數給它。

二、思路

我們知道知乎一些內容是需要登入才能看到,因此在爬取時的時候要先實現login,並把登入後的Cookies儲存下來,爬取其他頁面時將登入後的cookies一起傳遞過去,就可以已登入狀態請求其他頁面,所以核心在於如何儲存cookie和載入儲存的cookies的方式來記錄使用者的身份資訊。

2.1 利用selenium模擬瀏覽器登入,非常簡單和方便;

2.2 成功登入後,將登入的cookies儲存成檔案(此處通過json儲存)-------------第一步的關鍵步驟;

2.3 之後請求其他頁面時開啟儲存cookies的json檔案,並獲取檔案中的name和value值,構建cookies的字典dict;

2.4 發起請求時,帶上cookies=之間取出的dict型別的cookies。

通過上面的過程,我們就可以實現先通過login,記錄cookies,然後在訪問請求時帶上記錄的cookies訪問即可。

三、程式碼實現

環境:win10+py3.6

工具:Pycharm

關鍵依賴庫:Scrapy+selenium + json +time

通過scrapy構造spider的過程預設熟知,如有疑問可以微信新增:第一行Python程式碼;

詳細程式碼和註釋:

# -*- coding: utf-8 -*-

# 匯入依賴包
import scrapy
from selenium import webdriver
import time
import json

# 構建spider自動生成的基本配置
class ZhihuSpider(scrapy.Spider):
    name = 'zhihu'
    allowed_domains = ['www.zhihu.com']
    start_urls = ['http://www.zhihu.com/']
    
    # 模擬請求的headers,非常重要,不設定也可能知乎不讓你訪問請求
    headers = {
        "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0",
        "HOST": "www.zhihu.com"
    }


    # 第一步:使用selenium登入知乎並獲取登入後的cookies,cookies沒失效時,只要初次請求執行一次
    def loginZhihu(self):
        # 登入網址
        loginurl='https://www.zhihu.com/signin'
        # 載入webdriver驅動,用於獲取登入頁面標籤屬性
        driver=webdriver.Chrome()
        driver.get(loginurl)

        # 方式1 通過填充使用者名稱和密碼
        # driver.find_element_by_name('username').clear()  # 獲取使用者名稱框
        # driver.find_element_by_name('username').send_keys(u'username')  # 填充使用者名稱
        # driver.find_element_by_name('password').clear()  # 獲取密碼框
        # driver.find_element_by_name('password').send_keys(u'password')  # 填充密碼
        # time.sleep(10)  # 執行休眠10s等待瀏覽器的載入
        # input("檢查網頁是否有驗證碼要輸入,有就在網頁輸入驗證碼,輸入完後在編輯器中回車;如果無驗證碼,則直接回車")    
        # 非常關鍵,有時候知乎會在輸入密碼後彈出驗證碼,這一步可將程式碼執行暫時停滯
        # driver.find_element_by_css_selector("button[class='Button SignFlow-submitButton Button--primary Button--blue']").click()    # 點選登入按鈕

        # 方式2 直接通過掃描二維碼,如果不是要求全自動化,建議用這個,非常直接
        # 畢竟我們這一步只是想儲存登入後的cookies,至於用何種方式登入,可以不必過於計較
        time.sleep(10) # 同樣休眠10s等待頁面
        input("請頁面二維碼,並確認登入後,點選回車:")   #點選二維碼手機掃描登入
        # 通過上述的方式實現登入後,其實我們的cookies在瀏覽器中已經有了,我們要做的就是獲取
        cookies = driver.get_cookies()   # Selenium為我們提供了get_cookies來獲取登入cookies
        driver.close()  # 獲取cookies便可以關閉瀏覽器
        # 然後的關鍵就是儲存cookies,之後請求從檔案中讀取cookies就可以省去每次都要登入一次的
        # 當然可以把cookies返回回去,但是之後的每次請求都要先執行一次login沒有發揮cookies的作用
        jsonCookies=json.dumps(cookies)   # 通過json將cookies寫入檔案
        with open('zhihuCookies.json','w') as f:
            f.write(jsonCookies)
        print(cookies)
        # return cookies

    # Scrapy使用儲存ookies請求發現模組,看是否是登入之後的狀態
    def question(self,response):
        with open('zhihu_find.html','w',encoding='utf-8') as f:
            f.write(response.text)   #寫入檔案,儲存成.html檔案 
        pass


    def parse(self, response):
        pass

    # scrapy請求的開始時start_request
    def start_requests(self):
        zhihu_findUrl = 'https://www.zhihu.com/explore'
        self.loginZhihu() # 首次使用,先執行login,儲存cookies之後便可以註釋,
        # 畢竟每次執行都要登入還是挺麻煩的,我們要充分利用cookies的作用
        # 從檔案中獲取儲存的cookies
        with open('zhihuCookies.json','r',encoding='utf-8') as f:
            listcookies=json.loads(f.read()) # 獲取cookies
        # 把獲取的cookies處理成dict型別
        cookies_dict = dict()
        for cookie in listcookies:
            # 在儲存成dict時,我們其實只要cookies中的name和value,而domain等其他都可以不要
            cookies_dict[cookie['name']] = cookie['value']
        print(cookies_dict)
        # Scrapy發起其他頁面請求時,帶上cookies=cookies_dict即可,同時記得帶上header值,
        yield scrapy.Request(url=zhihu_findUrl,cookies=cookies_dict,callback=self.question,headers=self.headers)

通過上面的方法就可以實現,在請求其他頁面時也是登入之後的狀態,畢竟cookies作用之一就是記錄狀態的,當然儲存cookies之後你也可以試試將login_zhihu()的方法註釋,去請求其他頁面,只要我們的cookies不過期,效果都是一樣的。效果如下:

當然,除了通過儲存成dict型別,在請求時通過cookies=cookies_dict外,我們可以連串成字串,新增到headers頭部中,程式碼如下:

        with open('zhihuCookies.json','r',encoding='utf-8') as f:
            listcookies=json.loads(f.read())        
        cookie=[item["name"]+"="+item["value"] for item in listcookies]
        cookiestr="; ".join(item for item in cookie)
        print(cookiestr)

        headers = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko/20100101 Firefox/61.0",
            "HOST": "www.zhihu.com",
            "cookie": cookiestr    #從檔案中獲取並拼接的cookies
        }
        # 放在header是發起請求
        yield scrapy.Request(url=zhihu_findUrl,callback=self.question,headers=headers)

這種方法應該也是可行的,到時我到現在還沒有成功過,不知道是不是拼接cookies是不是哪裡寫錯了,大家成了幫我看看。

需要原始碼或者有其他指教,歡迎微信新增“第一行Python程式碼”,一起學習python程式碼。