Python3爬蟲學習筆記1.2——模擬登入
歡迎捧場,上一篇我們學習了urllib官方庫的一些使用方法,今天的主要工作內容是利用Python來模擬登入網站,我們選擇用知乎做實驗,前一段時間登入知乎好像需要驗證碼,現在又可以直接登陸了,比較簡單,也有各網站登入的普遍性,而且傳輸的過程中沒有對使用者名稱和密碼進行加密。PS:知乎有毒,2333。
Fiddler大法好
Fiddler是一個http協議除錯代理工具,我們在開啟Fiddler的執行環境下進行網路通訊時,它能夠記錄並檢查你的電腦和網際網路之間的http通訊。我們試著登入知乎後檢視一下Fiddler的情況。
點選登入,登入成功後看一眼 Fiddler 的情況,我們找到左側對應的連線,檢視我們向伺服器傳送了那些內容。
可以在右側的 WebForms 中清楚地看見自己的資訊,包括email、password、remember_me 以及一個很重要的 _xsrf。_xsrf 這個驗證欄位是我們想伺服器傳送網頁請求時,伺服器傳送過來的,然後我們再把這個 _xsrf 欄位傳送給 /login/email 這個 url ,只有攜帶好 email、password 和_xsrf這三個值,才能夠成功登入。
利用正則表示式查詢_xsrf。
compile('name=\"_xsrf\" value=\"(.*)\"', flags = 0)
將其封裝為函式。
def get_xsrf(data):
cer=re.compile('name=\"_xsrf\" value=\"(.*)\"' ,flag=0)
strlist=cer.findall(data)
return strlist[0]
這樣我們就能夠得到_xsrf驗證欄位的值了,為登入做準備。
Cookie
當你通過瀏覽器訪問一個網站時,伺服器會給你傳送一些資料,以保持Web伺服器與客戶端之間的狀態,這些資料就是Cookie。
指某些網站為了辨別使用者身份而儲存在使用者本地終端(Client Side)上的資料(通常經過加密)
我們直接登入知乎後檢視一下自己的Cookie,我們可以直接用Cookie作為 Request Headers 來登入知乎。
import urllib. request
web_header = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
'Cookie':'你的Cookie'
}
url_zhihu='https://www.zhihu.com'
req=urllib.request.Request(url=url_zhihu,headers=web_header)
resp=urllib.request.urlopen(req)
data=resp.read()
print(data.decode('utf-8'))
但是我們這樣會遇見一個感覺上莫名其妙的問題,如圖。
我們並沒有用“gbk”來解碼,錯誤的資訊提示卻是“gbk”錯誤,我們檢視一下知乎的原始碼。
知乎用的卻是是 utf-8 的編碼,那為什麼會出現UnicodeEncodeError問題呢?經過一番google後,差不多找到了原因。
Python中print()函式自身有限制,不能列印所有的unicode字元,print()函式的侷限就是Python預設編碼的侷限,因為作業系統是windows的,所以Python的預設編碼不是 utf-8 ,那麼我們改一下Python預設編碼就可以了。
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8') #改變標準輸出的預設編碼
修改後的程式碼如下:
#encoding='utf-8'
import io
import sys
import urllib.request
web_header = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36',
'Cookie':'你的Cookie'}
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf8')
url_zhihu='https://www.zhihu.com'
req=urllib.request.Request(url=url_zhihu,headers=web_header)
resp=urllib.request.urlopen(req)
data=resp.read()
print(data.decode('utf-8'))
執行後沒有出現UnicodeEncodeError,卻發現我們得到的網頁全是火星文,中文全是亂碼。
這個,不科學呀,明明已經改過來了為什麼不會這樣?其實主要原因是這個程式是在cmd中執行的,如果是在IDLE中執行,則正常顯示。我們也可以將編碼格式換為 “gb18030”。再次執行就可以了。
sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='gb18030')
編碼格式 | 編碼語言 |
---|---|
utf-8 | 所有語言 |
gbk ,gb2312,gb18030 | 簡體中文 |
big5,big5hkscs | 繁體中文 |
但是我們的爬蟲在登入的時候幾乎不會這麼做,因為Python給我們提供了一個完美的http.cookiejar庫來幫助我們處理Cookie,我們只需要在建立opener的時候將HTTPCookieProcessor放進去,就大功告成了。
import http.cookiejar
import urllib.request
def getOpener(head):
# deal with the Cookies
cj = http.cookiejar.CookieJar()
pro = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(pro)
header = []
for key, value in head.items():
elem = (key, value)
header.append(elem)
opener.addheaders = header
return opener
從伺服器下載cookie到本地,並且在傳送請求時帶上本地的 cookie。
網頁資料壓縮
Web伺服器傳送過來的資料可能是經過壓縮的,如果沒有將資料解壓的話,會出現各種錯誤。對於Python來說,它提供了非常方便的內建庫。
import gzip
def ungzip(data):
try:
print('準備解壓……')
data=gzip.decompress(data)
print('解壓完畢>')
expect:
print('無需解壓')
return data
通過 opener.read() 讀取回來的資料,經過 ungzip 處理後,再解碼 decode() 就可以得到正確的 str。
登入
在我們集齊玩所有的龍珠之後就可以,召喚神龍了。
import gzip
import re
import http.cookiejar
import urllib.request
import urllib.parse
def getXSRF(data):
cer = re.compile('name=\"_xsrf\" value=\"(.*)\"', flags = 0)
strlist = cer.findall(data)
return strlist[0]
def ungzip(data):
try: # 嘗試解壓
print('準備解壓.....')
data = gzip.decompress(data)
print('解壓完畢!')
except:
print('無需解壓')
return data
def getOpener(head):
cj = http.cookiejar.CookieJar()
pro = urllib.request.HTTPCookieProcessor(cj)
opener = urllib.request.build_opener(pro)
header = []
for key, value in head.items():
elem = (key, value)
header.append(elem)
opener.addheaders = header
return opener
header = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
url = 'https://www.zhihu.com/'
opener = getOpener(header)
op = opener.open(url)
data = op.read()
#data = ungzip(data) # 解壓
_xsrf = getXSRF(data.decode())
url += 'login/email'
email = 'your_email'
password = 'your_password'
postDict = {
'_xsrf':_xsrf,
'email': email,
'password': password,
'rememberme': 'true',
'captcha_type':'cn'
}
postData = urllib.parse.urlencode(postDict).encode()
op = opener.open(url, postData)
data = op.read()
#data = ungzip(data)
print(data.decode('utf-8'))
得到的我們在開啟Fiddler看一下剛才的執行程式時出現的HTTP請求。
同樣得到了如下程式碼。
{“r”:0,
“msg”: “\u767b\u5f55\u6210\u529f”
}
登入成功,大功告成!
下次我們將學習如何爬取網站中的特定文字內容,一起努力進步吧。