1. 程式人生 > >Python3爬蟲學習筆記1.2——模擬登入

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驗證欄位的值了,為登入做準備。

當你通過瀏覽器訪問一個網站時,伺服器會給你傳送一些資料,以保持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'))

但是我們這樣會遇見一個感覺上莫名其妙的問題,如圖。
error
我們並沒有用“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”
}

這裡寫圖片描述

登入成功,大功告成!
下次我們將學習如何爬取網站中的特定文字內容,一起努力進步吧。