新版知乎登錄之post請求

新版知乎登錄之post請求

來自專欄 Python程序員

前言

在上一篇文章中給大家講解了requests發送post請求的幾種方式,並分析了一些使用陷阱。

疑惑

在文章發表之後,有朋友給我留言說,知乎登錄就沒有使用提交Form表單(application/x-www-form-urlencoded)的方式,而是上傳文件(multipart/form-data),這是為什麼呢?知乎登錄post請求該怎麼發送呢?

本質

我想說的是一般情況下是使用提交Form表單的方式進行登錄,但是不排除其他的方式。大家要透過現象看本質,登錄驗證的本質上是客戶端發送驗證消息,服務端校驗消息,返迴響應。登錄驗證可以使用提交Form表單,可以使用發送ajax,也可以上傳驗證文件,甚至我不用http請求,使用Websocket,都是可以的,這沒必要糾結。好多朋友在知乎登錄的時候,就傻眼了?這個怎麼使用requests發送post請求呢?

新版知乎登錄分析

首先打開谷歌瀏覽器,同時F12,打開開發者模式,並勾選Preserve log

接著在知乎登錄首頁,輸入賬號與密碼,開始登錄。(這次不涉及驗證碼的分析)

知乎登錄請求如下圖,大家肯定注意到了content-type: multipart/form-data; boundary=----WebKitFormBoundarypxPm5bUFaA8CHOHo。不僅不是Form表單提交,而且和之前講的上傳文件還有區別,即boundary的配置。

requests模擬知乎登錄

上一篇文章里的文件上傳,post函數里使用的是files參數,通過這個參數來表明使用的是multipart/form-data編碼,這裡不再是通過files參數傳文件,而是傳參數,其實本質上一樣的,文件內容不就是這參數嗎?好,為了測試方便,向 httpbin.org/post 發送post請求,代碼如下:

  1. import requests
  2. url = "http://httpbin.org/post"
  3. fields = {
  4. "client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
  5. "grant_type": "password",
  6. "timestamp": "1527040472416",
  7. "source": "com.zhihu.web",
  8. "signature":"66a16483ab16e54c3bb4ef84bf683dd67cadc246",
  9. "username": "xxxxx@qq.com",
  10. "password": "xxxxxxxx"
  11. }
  12. res = requests.post(url, files=fields)
  13. print(res.request.body)
  14. print(res.request.headers)
  15. print(res.text)

從上面代碼中可以看到,files參數只不過變成了參數字典。在控制台的輸出效果如下:

列印的方式觀察的效果不是很好,不如使用http Analyzer 抓取發送的包更加直觀。對於http Analyzer的使用在我的書《Python爬蟲開發與項目實戰》中有講解。http Analyzer抓到的發送包請求頭截圖如下:

請求頭

payload信息如下,效果已經出來了。

post payload

從上面兩張圖中,我們發現我們寫的程序沒有問題,發送的post請求和知乎登錄的數據包差別不是很大。

boundary定製

要說和知乎登錄請求包還有什麼差別,也就是boundary的配置

知乎登錄的類似boundary=----WebKitFormBoundarypxPm5bUFaA8CHOHo,而我們寫的程序為boundary=f30cf72e14254d59a9824e694e10e2c0。肯定有聰明的小夥伴,已經開動腦筋,我們在requests單獨配置headers不就可以了?很不幸的告訴大家,這樣是不行的,雖然headers改變了,但是post數據中的boundary內容並沒有改變呢。這個時候我們要引入幫手requests_toolbelt

requests_toolbelt

requeststoolbelt是對requests的補充,是一個第三方輔助插件,通過這個插件就可以定製boundary。首先安裝requeststoolbelt:

pip3 install requests_toolbelt

定製代碼如下:

  1. import requests
  2. from requests_toolbelt import MultipartEncoder
  3. url = "http://httpbin.org/post"
  4. fields = {
  5. "client_id": "c3cef7c66a1843f8b3a9e6a1e3160e20",
  6. "grant_type": "password",
  7. "timestamp": "1527040472416",
  8. "source": "com.zhihu.web",
  9. "signature":"66a16483ab16e54c3bb4ef84bf683dd67cadc246",
  10. "username": "xxxxx@qq.com",
  11. "password": "xxxxxxxx"
  12. }
  13. m = MultipartEncoder(fields, boundary=----WebKitFormBoundaryWp8R1tWtqL2vhLuG)
  14. res = requests.post(url, headers={Content-Type: m.content_type}, data=m.to_string())
  15. print(res.request.body)
  16. # # 查看請求頭
  17. print(res.request.headers)
  18. print(res.text)

發送效果

這次直接使用http analyzer抓包看一下效果。

請求頭

post payload

福利大放送

關注公眾號:七夜安全博客

weixin.qq.com/r/_0StteP (二維碼自動識別)

  • 回復【1】:領取 Python數據分析 教程大禮包
  • 回復【2】:領取 Python Flask 全套教程
  • 回復【3】:領取 某學院 機器學習 教程
  • 回復【4】:領取 爬蟲 教程

知識星球已經快40人了,隨著人數的增多,價格之後會上漲,越早關注越多優惠。星球的福利有很多:

  • 比如上面的教程,已經提前在知識星球中分享
  • 可以發表一些問題,大家一塊解決
  • 我之後寫的電子書,錄製的教學視頻,對於知識星球的朋友都是優惠的(基本上免費)
  • 一些節假日會給大家發個紅包或者贈書

t.zsxq.com/iqNjYja (二維碼自動識別)


推薦閱讀:

爬蟲入門系列(二):優雅的HTTP庫requests
使用Python爬蟲下載電子書
一个关于python requests 和SSL证书的问题?

TAG:Python | 爬蟲計算機網路 | requests |