知乎登錄

知乎登錄

@(博客)[Python, 登錄, 知乎, 爬蟲]python

018.8.12git

背景

由於學年綜合實踐準備的一部分須要爬取知乎全站,因此爲了方便,自動登錄是頗有必要的。而因爲許多學習爬蟲的各友,都愛拿知乎練手——其實我倒非然,這算是第一次對知乎「開戰」,是客觀因素致使的必然——以致於知乎增強了反扒機制
這裏寫圖片描述github

我爬蟲經驗有限,實在不知該對這樣的加密如何下手,一番搜索引擎以後,獲得的都是過時操做。Github上找到了經過二維碼掃描登錄的思路,那就以此宣戰吧。chrome

也在此感謝這名網友的無私奉獻,點擊可查看json

題外話

說句題外話:切不能夠慣性思惟api

另:完整代碼已上傳Github,文章末尾有連接。裏邊的study文件是我整個思考過程當中產生的測試代碼,若是隻是須要實現知乎登錄,則study文件能夠直接刪除瀏覽器

環境

(1)python3.6
(2)主要第三方庫:
- requests
- PILpip3 install -i https://pypi.douban.com/simple/ pillow 利用豆瓣源,加快下載速度,由於直接安裝可能會出現timeout的錯誤cookie

(3)chromesession

尋找切入點

這裏寫圖片描述

第一步確定是先來到知乎提供二維碼登錄的界面,利用開發工具,可查看請求這個二維碼圖片須要那些數據
這裏寫圖片描述
這裏寫圖片描述工具

能看到是get請求,headers也很尋常,但屢次刷新可發現請求的url地址有一部分在改變
這裏寫圖片描述

這確定算不上什麼難點,咱們尋找前面的文件,能找到這部分動態改變的值
這裏寫圖片描述

爲了方便闡述,那就把image稱之爲A文件,qrcode成爲B文件。這裏就有了一個思路,先請求B文件,拿到token值之後,拼接成目的url,再去請求A文件

問題的轉移1

因而咱們從A遷移到了B

這裏寫圖片描述

可見請求B文件的時候,headers字段是真的不少,但絕對不會全部都必要,這隻能排除法了

以我拙見是這樣處理的,首先看清楚了,是POST請求(從爬蟲到如今也幾個月了,仍是爬了很多網站,真的不提交數據用post請求的,我第一次見,因此以前一直是慣性思惟的用get,而後一直請求失敗, 因此各位入門爬蟲的注意了,千萬注意了別掉坑裏
這裏寫圖片描述

複製了全部headers,作一次post的請求,再看看狀態碼是否是201(爲了不請求被重定向,建議打印請求內容,或者關閉重定向,後面皆以打印內充處理再也不單獨提示)(對應study/test1.py文件
這裏寫圖片描述

能夠說很OK,而後就開始排除法,首先去掉的是最經常使用不到的噻。經過幾輪排除下來,發現CookieUser-Agent是必要的,既然須要用到cookie,咱們就得維持會話,因此要實例化一個session對象了,實現以下:
session = requests.session()

順便也把Cookie分解了,看看須要哪些內容

for item in headers["Cookie"].split(";"):
    print(item.split("=")[0])

這裏寫圖片描述
這些很重要,可得記住了

問題的轉移2

那麼如何讓session對象持有完整的cookie呢?

咱們回到最初的起點,再來分析一下完整的過程
這裏寫圖片描述

打開開發者工具,刷新頁面,而後點擊二維碼登錄(固然,這裏建議你清除一下cookies,最好選擇【高級】而不是【基本】)

這裏寫圖片描述

咱們能夠看到第一次請求登錄界面的時候,請求是不帶cookies的;而請求以後,按照響應體的要求,會設置對應的_xsrf_zaptgw_17。前面咱們知道須要6個,這裏才三個確定是不夠的,因此繼續找signin後面的文件,看看到底有什麼貓膩在裏頭

因而在udid這個文件中,你會發現響應體要求設置q_c1d_c0;也就是說,在成功請求這個文件以後,Cookie就包含這兩個部分了
這裏寫圖片描述

照例複製下完整的headers,找到請求的url,以及請求方式(注意了!這裏也是post),最後排除法,找到必要的部分(對應study/test2.py文件
這裏寫圖片描述

仍然是Cookie以及User-Agent

繼續擼

還不夠,如今咱們的cookies還差capsion_ticket部分,因此繼續擼

因而找到了captcha?lang=cn文件,它的響應體告訴瀏覽器,能夠設置capsion_ticket
這裏寫圖片描述

對應study/test3.py文件
這裏寫圖片描述

開始代碼

有了這波分析,咱們就能夠開始動手敲代碼了

對應studyget-qrcode.py文件

import requests


session = requests.session()

HEADERS = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 \ (KHTML, like Gecko) Chrome/68.0.3440.84 Safari/537.36'
}

# 第一次請求,爲了Cookie(_xsrf,_zap,tgw_17)
session.get(url="https://www.zhihu.com/signin", headers=HEADERS)
# 第二次請求,爲了Cookie(q_c1,d_c0)
session.post(url="https://www.zhihu.com/udid", headers=HEADERS)
# 第三次請求,爲了Cookie(capsion_ticket)
session.get(url="https://www.zhihu.com/api/v3/oauth/captcha?lang=cn", headers=HEADERS)
# 第四次請求,爲了token,用於構建二維碼圖片的請求連接
response = session.post(url="https://www.zhihu.com/api/v3/account/api/login/qrcode", headers=HEADERS)
# print(response.json())

# 第五次請求,爲了二維碼圖片
url4QR = "https://www.zhihu.com/api/v3/account/api/login/qrcode/{0}/image".format(response.json().get("token"))

response = session.get(url=url4QR, headers=HEADERS)
if response.status_code == 200:
    with open("qr.jpg", "wb") as file:
        file.write(response.content)
    print("【保存二維碼成功】")
else:
    print("【請求二維碼圖片錯誤】")

運行結果以下
這裏寫圖片描述

這時候覺得掃描二維碼就登錄成功了嗎?然而沒有
咱們掃描一下網頁的二維碼登錄一下試試,會發如今手機上點擊確認登錄之後,請求知乎www.zhihu.com網頁的時候,Cookie又多了一個z_c0
這裏寫圖片描述

暈!可是扶住牆,老規矩。能夠看到距離知乎首頁文件最近的一個scan_info文件,說了要設置z_c0
這裏寫圖片描述

因而在咱們掃描二維碼以後,應該先請求這個文件,再請求首頁文件;查看請求的url,也能發現,這個文件也有一部分是動態的,並且正是以前獲取的token
這裏寫圖片描述

爲了確保咱們成功登錄,可測試編輯頁面,由於這個頁面只有在登錄成功後能夠訪問,否則就會被重定向到登錄頁面去
這裏寫圖片描述

添加代碼以下

# 阻塞程序,給予用戶掃描二維碼的時間
input("請隨便輸入後回車")

# 請求scan_info文件,並打印狀態碼
print(session.get("https://www.zhihu.com/api/v3/account/api/login/qrcode/{0}/scan_info".format(token), headers=HEADERS).status_code)

# 請求編輯頁面
response = session.get("https://www.zhihu.com/people/edit", headers=HEADERS, allow_redirects=False)
if response.status_code == 200:
    print("登錄成功")

    print(response.text[:10000])

嗯,寫到這兒的時候,宿舍斷網了,因而我打開手機熱點準備測試代碼(之因此要說這個細節,由於我不確實是否是由於使用的手機熱點,才形成了後面的錯誤),結果第一次請求的時候報了以下錯
這裏寫圖片描述

其實關閉SSL驗證就好,加上參數verify=False,加了這個參數之後會報InsecureRequestWarning警告,個人處理方式是關閉這個警告。加上以下代碼便可

from requests.packages import urllib3
from requests.packages.urllib3.exceptions import InsecureRequestWarning

urllib3.disable_warnings(InsecureRequestWarning)

好了,測試代碼吧。效果以下
這裏寫圖片描述

成功


華麗的分割線—————————————————————————

今天起來測試過了,的確是由於使用手機熱點才形成SLLError。不過我認爲也能夠加上以前的處理措施,避免所以出錯

完善代碼

如今基本功能實現了,但不夠完善
- 好比難道用戶每次使用都要登錄?咱們能夠設置本地cookies,這樣就能夠等cookies失效以後再登錄
- 好比難道每次用戶都要手動去打開二維碼圖片?咱們能夠利用PIL庫來實現圖片自動打開

如下是我程序的總體邏輯設計
這裏寫圖片描述

如下是我代碼的邏輯設計
這裏寫圖片描述


由於完整代碼已經上傳GitHub,有詳細註釋,就不在這細說了

相關文章
相關標籤/搜索