在之前的課程中,我們主要使用了requests的get方法來直接獲取網(wǎng)頁的內(nèi)容。支持GET方法的網(wǎng)頁,接受我們的URL, 從URL里面取出參數(shù),然后再將結(jié)果返回給瀏覽器。由于URL的長度是有限制的,所以只能接收少量的參數(shù)。而支持POST方法的網(wǎng)頁,可以傳遞大量的參數(shù)和大量的信息。如果一個網(wǎng)頁只支持POST方法,那這個網(wǎng)頁是沒有辦法在瀏覽器里面直接輸入網(wǎng)址訪問的。requests的post方法支持將參數(shù)以POST方式提交給網(wǎng)頁,并得到網(wǎng)頁的返回信息。
大多數(shù)的網(wǎng)站,登錄的用戶名和密碼都是通過POST方式提交給服務(wù)器的,因此如果可以模擬網(wǎng)站的這個提交行為,就可以模擬登錄網(wǎng)站。
我們首先進入知乎的登錄頁面,打開Chrome的開發(fā)者工具的Network選項卡,勾選“Preserve log”并故意輸入錯誤的賬號和密碼嘗試登錄,從Chrome抓取到的數(shù)據(jù)中我們可以找到我們需要的信息:


從以上兩張圖中,我們可以看到,當(dāng)我們點擊了登錄按鈕以后,程序會將圖二紅框中的Form Data下面四個數(shù)據(jù)使用POST方式發(fā)送給圖一紅框中的https://www.zhihu.com/login/email這個URL。
注意:如果你輸入的賬號不是手機號,而是郵箱,數(shù)據(jù)將會發(fā)送到的URL為:https://www.zhihu.com/login/phone_num
上圖中的Form Data,后三項的意義顯而易見,email: 郵箱, password: 密碼, remember_me: 記住我。但是第一項"_xsrf"是什么意思?它后面的一長串?dāng)?shù)據(jù)是哪里來的?
這個時候大家打開登錄頁面的源代碼,你將會找到這樣內(nèi)容:

那么事情就簡單了,使用正則表達式或者XPath先從源代碼里面把這個xsrf提取出來,然后再和登錄信息一起提交即可。
還有一點需要注意:在Form Data中,remember_me后面的值是true, 首字母是小寫的。但是在Python里面的布爾值True, 首字母需要大寫。
在一般情況下是不需要使用驗證碼登錄的,所以只需要提供圖二列出的信息,將它們寫成一個字典并POST提交就能實現(xiàn)登錄。那么如果遇到驗證碼怎么辦呢?后面我們會有專門的課程將驗證碼的處理。
現(xiàn)在,我們已經(jīng)知道了登錄知乎的原理,于是就可以通過代碼來實現(xiàn)登錄。核心代碼如下:
data = {'_xsrf': xsrf,'email':'郵箱','password':'密碼','remember_me':True}session = requests.Session()result = session.post('https://www.zhihu.com/login/email', headers=header, data=data)#這里的result是一個json格式的字符串,里面包含了登錄結(jié)果#之后訪問知乎的其他頁面,只需要使用session.get('網(wǎng)址', headers=header)這種格式front_page = session.get('https://www.zhihu.com', headers=header)print(front_page.content.decode())
其運行效果如下圖所示:

網(wǎng)址返回的登錄結(jié)果是登錄成功,并且查看源代碼可以證明是登錄成功。
對于其他的網(wǎng)站,整個流程是完全一樣的,只是POST提交的參數(shù)各有不同。有些網(wǎng)址只需要POST提交用戶名和密碼就可以了,而另外一些網(wǎng)址,可能還需要從源代碼里面提取更多的參數(shù)。