Cookie 和模擬登陸
什么是 Cookie
在網(wǎng)站中,http請(qǐng)求是無(wú)狀態(tài)的。也就是說(shuō)即使第一次和服務(wù)器連接后并且登陸成功后,第二次請(qǐng)求服務(wù)器依然不能知道當(dāng)前請(qǐng)求是哪個(gè)用戶。Cookie 的出現(xiàn)就是為了解決這個(gè)問(wèn)題,第一次登陸后服務(wù)器返回一些數(shù)據(jù)(Cookie)給瀏覽器,然后瀏覽器保存在本地,當(dāng)該用戶發(fā)送第二次請(qǐng)求時(shí),就會(huì)自動(dòng)地把上次請(qǐng)求存儲(chǔ)的 Cookie 數(shù)據(jù)自動(dòng)攜帶給服務(wù)器,服務(wù)器通過(guò)瀏覽器攜帶的數(shù)據(jù)就能判斷當(dāng)前用戶是哪個(gè)了。Cookie 存儲(chǔ)的數(shù)據(jù)量有限,不同的瀏覽器有不同的存儲(chǔ)大小,但一般不超過(guò) 4KB。因此使用 Cookie 只能存儲(chǔ)一些少量的數(shù)據(jù)。
Cookie 的格式
Set-Cookie: NAME=VALUE; Expires/Max-age=DATE; Path=PATH; Domain=DOMAIN_NAME; SECURE
以上參數(shù)的意義:
- NAME:cookie的名字
- VALUE: cookie的值
- Expires:cookie的過(guò)期時(shí)間
- Path:cookie 作用的路徑
- Domain: cookie 作用的域名
- SECURE:是否只在 https 下起作用
使用 cookielib 庫(kù)和 HTTPCookieProcessor 模擬登錄
這里以人人網(wǎng)為例。人人網(wǎng)中,要訪問(wèn)某人的主頁(yè),必須先登錄才能訪問(wèn),說(shuō)白了就是要有 cookie 信息。如果我們想要用代碼的形式訪問(wèn),就必須要有正確的 cookie 信息才能訪問(wèn),就必須要用正確的 cookie 信息才能訪問(wèn)。解決方案有兩種,第一種是使用瀏覽器來(lái)訪問(wèn),然后將 cookie 信息復(fù)制下來(lái),放到 headers 中。示例代碼如下:
【這里代碼,為了方便,用了微博做示例】
from urllib import request
targetUrl = 'https://weibo.com/tmac1010?is_all=1'
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36",
"Cookie": "TC-V5-G0=4e714161a27175839f5a8e7411c8b98c; login_sid_t=53c6e5764e8f408b6f7ca86e68e45970; cross_origin_proto=SSL; Ugrow-G0=5c7144e56a57a456abed1d1511ad79e8; _s_tentry=passport.weibo.com; wb_view_log=1440*9002; Apache=9886055519552.01.1560870771483; SINAGLOBAL=9886055519552.01.1560870771483; ULV=1560870771489:1:1:1:9886055519552.01.1560870771483:; SUB=_2A25wDI_ADeRhGedL6lAZ9CjEyD-IHXVTe-YIrDV8PUNbmtAKLWmhkW9NVUrLigI8dTR7Y-Ij_ZhFA6RAvTQ42kDG; SUBP=0033WrSXqPxfM725Ws9jqgMF55529P9D9WW6Yu6WoZM-XpHg76dgWodm5JpX5KzhUgL.Fo2feKzRShqRe0e2dJLoI7pkPcLVIPB7eh2pPfYt; SUHB=0103HP7kXd88kZ; ALF=1592406800; SSOLoginState=1560870800; wvr=6; wb_view_log_1512846833=1440*9002; wb_timefeed_1512846833=1; webim_unReadCount=%7B%22time%22%3A1560872470141%2C%22dm_pub_total%22%3A2%2C%22chat_group_pc%22%3A0%2C%22allcountNum%22%3A2%2C%22msgbox%22%3A0%7D; TC-Page-G0=7f6863db1952ff8adac0858ad5825a3b|1560872474|1560872474"
}
reqObj = request.Request(url=targetUrl, headers=headers)
resp = request.urlopen(reqObj)
print(resp.read().decode('utf-8'))
但是每次在訪問(wèn)需要 cookie 的頁(yè)面都要從瀏覽器中復(fù)制 cookie 比較麻煩。Python 處理 cookie,一般是通過(guò) http.cookiejar 模塊和 urllib 模塊的 HTTPCookieProcessor 處理器類一起使用。http.cookiejar 模塊主要作用是提供用于存儲(chǔ) cookie 的對(duì)象。而 HTTPCookieProcessor 處理器主要作用是處理這些 cookie 對(duì)象,并構(gòu)建 handler 對(duì)象。
http.cookiejar 模塊
該模塊主要的類有 CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。這四個(gè)類的作用分別如下:
- CookieJar
管理 HTTP cookie 的值、存儲(chǔ) HTTP 請(qǐng)求生成的 cookie、向傳出的 HTTP 請(qǐng)求添加 cookie 的對(duì)象。整個(gè) cookie 都存儲(chǔ)在內(nèi)存中,對(duì) CookieJar 實(shí)例進(jìn)行垃圾回收后 cookie 也將丟失。
- FileCookieJar (filename, delayload=None, policy=None)
從 CookieJar 派生而來(lái),用來(lái)創(chuàng)建 FileCookieJar 實(shí)例,檢索 cookie 信息并將 cookie 存儲(chǔ)到文件中。filename 是存儲(chǔ) cookie 的文件名。delayload 為 True 時(shí)支持延遲訪問(wèn)文件,即只有在需要時(shí)才讀取文件或在文件中存儲(chǔ)數(shù)據(jù)。
- MozillaCookieJar (filename, delayload=None, policy=None)
從 FileCookieJar 派生而來(lái),創(chuàng)建與 Mozilla 瀏覽器 cookies.txt 兼容的 FileCookieJar 實(shí)例。
- LWPCookieJar (filename, delayload=None, policy=None)
從 FileCookieJar 派生而來(lái),創(chuàng)建與 libwww-per 標(biāo)準(zhǔn)的 Set-Cookie3 文件格式兼容的 FileCookieJar 實(shí)例。
利用 http.cookiejar 和 request.HTTPCookieProcessor 登錄人人網(wǎng)。
from urllib import request,parse
from http.cookiejar import CookieJar
# 1.登錄
# 1.1 創(chuàng)建一個(gè) CookieJar 對(duì)象
cookieJar = CookieJar()
# 1.2 使用 CookirJar 創(chuàng)建一個(gè) HTTPCookieProcess 對(duì)象
handler = request.HTTPCookieProcessor(cookieJar)
# 1.3 使用上一步創(chuàng)建的 handler 創(chuàng)建一個(gè) opener
opener = request.build_opener(handler)
# 1.4 使用 opener 發(fā)送登錄的請(qǐng)求
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
}
datas = {
'email':'xxxxxxxxxxx',
'password':'xxxxxxxxxx'
}
loginUrl = 'http://www.renren.com/PLogin.do'
reqObj = request.Request(loginUrl, data=parse.urlencode(datas).encode('utf-8'), headers=headers)
opener.open(reqObj)
# 2.訪問(wèn)個(gè)人主頁(yè)
homePageUrl = 'http://www.renren.com/320922841/profile'
reqObj = request.Request(homePageUrl, headers=headers)
respObj = opener.open(reqObj)
with open('files/renren.html', 'w') as f:
f.write(respObj.read().decode('utf-8'))
保存 Cookie 到本地
保存 cookie 到本地,可以使用 cookiejar 的 save 方法
from urllib import request
from http.cookiejar import MozillaCookieJar
cookieJar = MozillaCookieJar('files/cookie.txt')
handler = request.HTTPCookieProcessor(cookieJar)
opener = request.build_opener(handler)
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36',
}
req = request.Request('http://httpbin.org/cookies', headers=headers)
resp = opener.open(req)
for ck in cookieJar:
print(ck)
cookieJar.save(ignore_discard=True, ignore_expires=True)
# cookieJar.load(filename) # 從文件中讀取 cookie 信息