Python 從零開始爬蟲(九)——模擬登陸,cookie的使用

某些網站,登陸和沒登陸,用戶的權限是不同的,賬號登陸以後才能獲取更多的信息。更有甚者一上來就是登陸界面,不登陸就不給你進去(如p站)。爬取目標不用登陸當然是好,但須要時也沒辦法啊,這時若是還想爬取信息,就必須讓爬蟲學會登陸。html

Cookie

說到這裏就要介紹一下本文的小主角cookie了,簡單的說,cookie是服務器安在客戶端的「監視器」,記錄了包括登陸狀態在內的全部信息,這些信息由服務器生成和解釋,服務器經過客戶端攜帶的cookie來識別用戶。cookie存在生命週期,短的關掉瀏覽器就失效,長的能若干天免登錄,一旦失效就要從新獲取。因此只要獲得登陸後的cookie並必要時進行更新,服務器就會認定其爲登陸狀態。本文將介紹幾種主流方法來模擬登陸python

注意:並非說學會這幾種方法你就徹底掌握了模擬登陸,加密,驗證系統也可能成爲模擬登陸的頭號勁敵,若是查遍全網都沒獲得滿意的答案,selenium大佬也被識別了,那估計是沒救了程序員

從瀏覽器獲取

這是最簡單也是最容易見效的方法,在瀏覽器上登陸並進行足夠多操做後得到便能獲得足量的cookie,打開F12捉包觀其headers便可
圖片描述web

圖中上方的set-cookie是響應cookie,也就是服務器要保存在客戶端的cookie;下方的cookie則是要提交給服務器的cookie,也是咱們的目標,讓requests使用這個cookie有兩種方法,一是原封不動把cookie字符串放入headers字典中提交,二是把cookie字符串變成字典再由cookies參數提交,轉換方法以下。算法

def cookie_to_dict(cookie):
    cookie_dict = {}
    items = cookie.split(';')
    for item in items:
        key = item.split('=')[0].replace(' ', '')
        value = item.split('=')[1]
        cookie_dict[key] = value
    return cookie_dict

這種直接獲取的方法缺點也很明顯,就是不能追蹤set-cookie並更新,原來的cookie一旦失效,就要重新手動獲取瀏覽器

session維持

session名爲「會話」,即多個請求的行爲。requests庫提供了會話對象(requests.Session)讓使用者能跨請求保持某些參數如cookie,並且能自動處理服務器發來的cookie,使得同一個會話中的請求都帶上最新的cookie,很是適合模擬登陸。使用上也很是簡單,實例化後幾乎至關於一個requests對象擁有get,post等方法,text,cotent等屬性。爲了方便下次登陸,還能夠把第一次session登陸後的cookie經過cookiejar保存到本地供下次讀取免去登陸服務器

import requests
import http.cookiejar as cj
r = requests.session()
r.cookies = cj.LWPCookieJar()  # 接入容器
r.get(url,headers=,cookie=) # 不過須要注意,就算使用了會話,方法級別的參數也不會被跨請求保持,此cookie只發送給該請求
print(r.text)
r.post(url,headers=,data=,)
#請求x N
r.cookies.save(filename='cookies.txt', ignore_discard=True, ignore_expires=True)  # 保存cookie到本地,忽略關閉瀏覽器丟失,忽略失效
r.close() # 對話支持with打開以實現自動close


'''#載入本地cookie
s = requests.session()
s.cookies = cj.LWPCookieJar(filename='cookies.txt')
s.cookies.load(filename='cookies.txt', ignore_discard=True)
'''

雖然說session使cookie管理變得一勞永逸,但登陸包中post參數的構造多是一個深坑,post的是賬號密碼明文那簡單;蛋疼的是若是賬號密碼連同其餘數據經js加密成密文做爲post數據,那你就得從js中挑選並分析加密算法,還要用python實現(某些加了混淆的js像天書同樣)。若是沒法破譯加密,requests登陸就是一張白紙,cookie就更不用談了,給你再牛逼的管理工具也沒用。同時對方程序員的勤奮程度也是一個考慮因素,別人常常改算法,你也要重新看js改代碼。cookie

-----------------------------看看人家知乎,加密到連名字都沒有了,js還混淆,如何下手?-------------------------------
圖片描述session

綜上,session適用於沒有加密的登陸或者加密算法比較簡單而且不常更新的網站。趕上無解的加密算法?要麼手操拷貝cookie,要麼請selenium大佬出場。多線程

selenium大法

大佬雖然是慢了點,但永遠是你大佬。藉助瀏覽器完備的js解析能力,你根本不用考慮它是如何加密的,只要輸入帳號密碼,最多再加個驗證碼,瀏覽器直接運行js把他們直接變成密文並post過去,完成登陸,就像咱們平時操做那麼簡單。因此有一種巧妙的方法是先用selenium進行模擬登陸,而後再提取cookie給session用免去session模擬登陸的過程(固然也能夠繼續selenium下去)。在代碼中,每每就是定位,點擊,定位,發送賬號密碼,Enter(或者定位點擊登陸鍵),等待一段時間讓cookie加載完後將其打包成RequestsCookieJar給session用就能夠了。如對付知乎能夠這樣作:

import requests
from selenium import webdriver
import time
from selenium.webdriver.common.keys import Keys

driver = webdriver.Chrome()
driver.maximize_window()
driver.get('https://www.zhihu.com/')
# 不考慮驗證碼的狀況
driver.find_element_by_xpath('//button[@data-za-detail-view-id="2278"]').click() #點擊登陸進入登陸界面
driver.find_element_by_xpath('//input[@name="username"]').send_keys('account') #發送賬號名
driver.find_element_by_xpath('//input[@name="password"]').send_keys('password',Keys.ENTER) #發送密碼並回車
time.sleep(10) # 等待cookie加載完成
cookies = driver.get_cookies()
print(cookies)

s=requests.Session()
c = requests.cookies.RequestsCookieJar()
for item in cookies:
    c.set(item["name"],item["value"])
print(c)
s.cookies.update(c) # 載入cookie
#s.get()
#s.post()

'''
'''

但就算是大佬,也不是萬能的,有些網站能識別人操做的瀏覽器和selenium操做的瀏覽器,使登陸受到拒絕,譬如用selenium模擬登陸網易雲音樂就會提示登陸異常。若是不能對js進行逆向工程分析出其識別算法,那隻能放棄selenium走requests那條要分析加密的老路

後記

到系列第十篇文章,爬蟲系列也將接近尾聲,最後的內容是多線程,多進程及協程的介紹及使用。至於scrapy應該就不會講了,半年前剛入爬蟲坑學的,學得淺,如今忘得差很少了,現在又被深度學習帶跑了,但不排除忽然復活的可能。心急的小夥伴能夠去觀摩大佬們的代碼自學。本人就去挖DeepLearning的坑了。

相關文章
相關標籤/搜索