為爬蟲獲取登入cookies: 使用browsercookie從瀏覽器獲取cookies

王平發表於2018-12-03

上一節,我們使用Charles記錄微博的登入過程,並從中解析出了微博的登入細節,還用Python模擬實現了整個過程。只要微博登入不改變,我們的程式碼就一直可用,這也算是一勞永逸的事情了,而且程式執行中不需要人工參與,高度自動化。記得之前微博還是有驗證碼的,這次重新實現的這個過程中沒有發現驗證碼的蛛絲馬跡。

browsercookie的使用

完全用Python實現模擬登入的過程其實是很累的,考驗的是耐力、觀察力、聯想能力等等。雖然累,但一旦完成後面就省心了,也算是值得一試。

然而世事無常,並非所有登入都像微博那樣無驗證碼(也許有,只是沒有跳出來),更多的是像12306,知乎,嗶哩嗶哩那樣上了變態的驗證碼的。有時候為了自動識別驗證碼耗費的精力之大難以想象,所以我們寫爬蟲時,要綜合考量投入產出比,人工輸入驗證碼可能是更快捷便利的方法。

今天,我們就介紹一款專門從瀏覽器快取的cookies獲取cookies的工具,一個Python的模組:browsercookie。
它是一個很有用的爬蟲工具,通過載入你瀏覽器的cookies到一個cookiejar物件裡面,讓你輕鬆下載需要登入的網頁內容。

browsercookie 的安裝

它的原始碼在bitbucket上: browsercookie

可以從原始碼安裝,或者直接pip安裝

pip install browsercookie

需要注意的是,在Windows系統下,內建的sqlite模組在載入FireFox資料庫時會丟擲錯誤。需要更新sqlite的版本:

pip install pysqlite

browsercookie 的使用

我們拿百度的首頁來做實驗,如果沒有登入cookies,開啟的首頁右上角選單欄顯示登入而不顯示使用者名稱,如果有登入cookies,首頁則顯示使用者名稱而不顯示登入,通過在得到的html中搜尋“登入”來驗證這兩者的不同準備工作就是,要先開啟瀏覽器(比如Chrome, 或Firefox)登入一下百度,然後就可以關掉瀏覽器了,當然開著也無所謂。

首先,我們看看未登入狀態下得到的標題:

In [1]: import requests
In [2]: url = 'https://baidu.com/'
In [3]: r1 = requests.get(url)
In [4]: r1.content.decode('utf-8').find('登入')
Out[4]: 1580
In [5]: r1.content.decode('utf8').find('user-name')
Out[5]: -1

由上面的實驗我們看出來,沒有cookies請求得到登入的資訊,‘user-name’是顯示登入名時的css的class,通過查詢user-name再次確認沒有登入。

然後,在看看從瀏覽器獲得cookies後得到的標題:

In [11]: cjff = browsercookie.firefox()
In [12]: header = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Safari/537.36'}
In [13]: r2 = requests.get(url, cookies=cjff, headers=header)
In [14]: r2.content.decode('utf8').find('登入')
Out[14]: -1
In [15]: r2.content.decode('utf8').find('user-name')
Out[15]: 5038

通過上面的程式碼,我們驗證了從browsercookie獲取cookies併成功登入的百度。

細心的小猿們可能已經發現了,我用的cookies是從Firefox那裡得來的 <code>cjff = browsercookie.firefox()</code>
原因是,我先實驗從Chrome那裡獲取cookies,得到的cookies裡面確實也包含百度,但是就是不能登入,於是改用Firefox就輕鬆登入了。看來這個模組還不是很完美,小猿們也可以抽空研究一下其中緣由,給作者提個修改意見啥的。

browsercookie 的缺憾

前面我們也提到了從Chrome獲得的cookies不能登入百度的問題,後來我又實驗了幾個不同的網站,有的可以也有不可以的,再次證明了這個模組的不完美。

不過,這個庫用起來很簡單,幾行程式碼就可以驗證它對我們要登入的網站是否起作用,所以,寫爬蟲遇到登入的問題不妨先拿它驗證一下,萬一行呢,不就省了很多精力。

還有一類問題,就是你得到了cookies,訪問任何該網站的URL,它都先返回一段登入驗證的html,裡面通過JS重定向到不同的網址,你需要進一步解析這段JS程式碼才能訪問到你真正想訪問的目標網址,這樣的操作就比較累人,這樣的網站對爬蟲很不友好。別猜了,我說的就是微博。

        <html>
        <head>
        <title>新浪通行證</title>
        <meta http-equiv="refresh" content="0; url='https://login.sina.com.cn/crossdomain2.php?action=login&entry=miniblog&r=https%3A%2F%2Fpassport.weibo.com%2Fwbsso%2Flogin%3Fssosavestate%3D1574046135%26url%3Dhttps%253A%252F%252Fweibo.com%252Fkaifulee%26display%3D0%26ticket%3DST-MTM3MTQ1MzA0MA%3D%3D-1542510135-gz-E235393C87F25EE4E30B221C2B5F7F37-1%26retcode%3D0&login_time=1542509978&sign=d531a8b4eed9c403'"/>
        <meta http-equiv="Content-Type" content="text/html; charset=GBK" />
        </head>
        <body bgcolor="#ffffff" text="#000000" link="#0000cc" vlink="#551a8b" alink="#ff0000">
        <script type="text/javascript" language="javascript">
        location.replace("https://login.sina.com.cn/crossdomain2.php?action=login&entry=miniblog&r=https%3A%2F%2Fpassport.weibo.com%2Fwbsso%2Flogin%3Fssosavestate%3D1574046135%26url%3Dhttps%253A%252F%252Fweibo.com%252Fkaifulee%26display%3D0%26ticket%3DST-MTM3MTQ1MzA0MA%3D%3D-1542510135-gz-E235393C87F25EE4E30B221C2B5F7F37-1%26retcode%3D0&login_time=1542509978&sign=d531a8b4eed9c403");
        </script>
        </body>
        </html>

這種非同步載入的網頁越來越多,尤其是前端框架ReactJS, VueJS等框架的出現讓前後端分離,由瀏覽器執行JavaScript來渲染前端。這個時候,就需要我們的爬蟲支援JavaScript的執行,此時此刻,requests等單純的HTTP協議庫已經無能為力了,我們需要更強大的工具!欲知後事如何,且聽下回分解。

猿人學banner宣傳圖

我的公眾號:猿人學 Python 上會分享更多心得體會,敬請關注。

***版權申明:若沒有特殊說明,文章皆是猿人學 yuanrenxue.com 原創,沒有猿人學授權,請勿以任何形式轉載。***

相關文章