Python爬蟲之模擬知乎登陸

常常寫爬蟲的都知道,有些頁面在登陸以前是被禁止抓取的,好比知乎的話題頁面就要求用戶登陸才能訪問,而 「登陸」 離不開 HTTP 中的 Cookie 技術。html

登陸原理

Cookie 的原理很是簡單,由於 HTTP 是一種無狀態的協議,所以爲了在無狀態的 HTTP 協議之上維護會話(session)狀態,讓服務器知道當前是和哪一個客戶在打交道,Cookie 技術出現了 ,Cookie 至關因而服務端分配給客戶端的一個標識。python

cookie

  1. 瀏覽器第一次發起 HTTP 請求時,沒有攜帶任何 Cookie 信息
  2. 服務器把 HTTP 響應,同時還有一個 Cookie 信息,一塊兒返回給瀏覽器
  3. 瀏覽器第二次請求就把服務器返回的 Cookie 信息一塊兒發送給服務器
  4. 服務器收到HTTP請求,發現請求頭中有Cookie字段, 便知道以前就和這個用戶打過交道了。

實戰應用

用過知乎的都知道,只要提供用戶名和密碼以及驗證碼以後便可登陸。固然,這只是咱們眼中看到的現象。而背後隱藏的技術細節就須要藉助瀏覽器來挖掘了。如今咱們就用 Chrome 來查看當咱們填完表單後,究竟發生了什麼?git

(若是已經登陸的,先退出)首先進入知乎的登陸頁面 www.zhihu.com/#signin ,打開 Chrome 的開發者工具條(按 F12)先嚐試輸入一個錯誤的驗證碼觀察瀏覽器是如何發送請求的。github

從瀏覽器的請求能夠發現幾個關鍵的信息json

  1. 登陸的 URL 地址是 www.zhihu.com/login/email
  2. 登陸須要提供的表單數據有4個:用戶名(email)、密碼(password)、驗證碼(captcha)、_xsrf。
  3. 獲取驗證碼的URL地址是 www.zhihu.com/captcha.gif…

_xsrf 是什麼?若是你對CSRF(跨站請求僞造)攻擊很是熟悉的話,那麼你必定知道它的做用,xsrf是一串僞隨機數,它是用於防止跨站請求僞造的。它通常存在網頁的 form 表單標籤中,爲了證明這一點,能夠在頁面上搜索 「xsrf」,果真,_xsrf在一個隱藏的 input 標籤中瀏覽器

摸清了瀏覽器登陸時所須要的數據是如何獲取以後,那麼如今就能夠開始寫代碼用 Python 模擬瀏覽器來登陸了。登陸時所依賴的兩個第三方庫是 requests 和 BeautifulSoup,先安裝服務器

pip install beautifulsoup4==4.5.3
pip install requests==2.13.0複製代碼

http.cookiejar 模塊可用於自動處理HTTP Cookie,LWPCookieJar 對象就是對 cookies 的封裝,它支持把 cookies 保存到文件以及從文件中加載。cookie

而 session 對象 提供了 Cookie 的持久化,鏈接池功能,能夠經過 session 對象發送請求session

首先從cookies.txt 文件中加載 cookie信息,由於首次運行尚未cookie,全部會出現 LoadError 異常。工具

from http import cookiejar
session = requests.session()
session.cookies = cookiejar.LWPCookieJar(filename='cookies.txt')
try:
    session.cookies.load(ignore_discard=True)
except LoadError:
    print("load cookies failed")複製代碼

獲取 xsrf

前面已經找到了 xsrf 所在的標籤,,利用 BeatifulSoup 的 find 方法能夠很是便捷的獲取該值

def get_xsrf():
    response = session.get("https://www.zhihu.com", headers=headers)
    soup = BeautifulSoup(response.content, "html.parser")
    xsrf = soup.find('input', attrs={"name": "_xsrf"}).get("value")
    return xsrf複製代碼

獲取驗證碼

驗證碼是經過 /captcha.gif 接口返回的,這裏咱們把驗證碼圖片下載保存到當前目錄,由人工識別,固然你能夠用第三方支持庫來自動識別,好比 pytesser。

def get_captcha():
    """ 把驗證碼圖片保存到當前目錄,手動識別驗證碼 :return: """
    t = str(int(time.time() * 1000))
    captcha_url = 'https://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
    r = session.get(captcha_url, headers=headers)
    with open('captcha.jpg', 'wb') as f:
        f.write(r.content)
    captcha = input("驗證碼:")
    return captcha複製代碼

登陸

一切參數準備就緒以後,就能夠請求登陸接口了。

def login(email, password):
    login_url = 'https://www.zhihu.com/login/email'
    data = {
        'email': email,
        'password': password,
        '_xsrf': get_xsrf(),
        "captcha": get_captcha(),
        'remember_me': 'true'}
    response = session.post(login_url, data=data, headers=headers)
    login_code = response.json()
    print(login_code['msg'])
    for i in session.cookies:
        print(i)
    session.cookies.save()複製代碼

請求成功後,session 會自動把 服務端的返回的cookie 信息填充到 session.cookies 對象中,下次請求時,客戶端就能夠自動攜帶這些cookie去訪問那些須要登陸的頁面了。

源碼:github.com/lzjun567/cr…

參考資料:

相關文章
相關標籤/搜索