1. 程式人生 > >[Python]網路爬蟲(三):使用cookiejar管理cookie 以及 模擬登入知乎

[Python]網路爬蟲(三):使用cookiejar管理cookie 以及 模擬登入知乎

大家好哈,上一節我們研究了一下爬蟲的異常處理問題,那麼接下來我們一起來看一下Cookie的使用。

為什麼要使用Cookie呢?

Cookie,指某些網站為了辨別使用者身份、進行session跟蹤而儲存在使用者本地終端上的資料(通常經過加密)

比如說有些網站需要登入後才能訪問某個頁面,在登入之前,你想抓取某個頁面內容是不允許的。那麼我們可以利用python3的cookiejar模組來儲存cookie資訊,然後模擬登入。

在此之前呢,我們必須先介紹一個opener的概念。

1.Opener

當你獲取一個URL你使用一個opener。在前面,我們都是使用的預設的opener,也就是urlopen。它是一個特殊的opener,可以理解成opener的一個特殊例項,傳入的引數僅僅是url,data,timeout。

如果我們需要用到Cookie,只用這個opener是不能達到目的的,所以我們需要建立更一般的opener來實現對Cookie的設定。

2.Cookiejar

cookiejar模組的主要作用是提供可儲存cookie的物件,以便於與urllib模組配合使用來訪問Internet資源。Cookiejar模組非常強大,我們可以利用本模組的CookieJar類的物件來捕獲cookie並在後續連線請求時重新發送,比如可以實現模擬登入功能。該模組主要的物件有CookieJar、FileCookieJar、MozillaCookieJar、LWPCookieJar。

它們的關係:CookieJar —-派生—->FileCookieJar  —-派生—–>MozillaCookieJar和LWPCookieJar

1)獲取Cookie儲存到變數

首先,我們先利用CookieJar物件實現獲取cookie的功能,儲存到變數中,先來感受一下

12345678910111213from urllib import requestfrom urllib import parsefrom http import cookiejar#宣告一個CookieJar物件例項來儲存cookiecookie=cookiejar.CookieJar()#利用urllib庫中的request的HTTPCookieProcessor物件來建立cookie處理器handler=request.HTTPCookieProcessor
(cookie)#通過handler來構建openeropener=request.build_opener(handler)#此處的open方法同urllib的urlopen方法,也可以傳入requestresponse=opener.open('http://www.baidu.com')foritem incookie:print ('Name = '+item.name)print ('Value = '+item.value)

我們使用以上方法將cookie儲存到變數中,然後打印出了cookie中的值,執行結果如下

1 2 3 4 5 6 7 8 9 10 Name = BAIDUID
Value = 5C63AF95C94F5EE96BC89EE5E9CE0188:FG=1
Name = BIDUPSID
Value = 5C63AF95C94F5EE96BC89EE5E9CE0188
Name = H_PS_PSSID
Value = 1431_24557_21123_24022_20928
Name = PSTM
Value = 1508901974
Name = BDSVRTM
Value = 0
Name = BD_HOME
Value = 0

2)儲存Cookie到檔案

在上面的方法中,我們將cookie儲存到了cookie這個變數中,如果我們想將cookie儲存到檔案中該怎麼做呢?這時,我們就要用到

FileCookieJar這個物件了,建立LWPCookieJar例項,可以存Set-Cookie3型別的檔案。而MozillaCookieJar類是存為'.txt'格式的檔案.在這裡我們使用它的子類MozillaCookieJar來實現Cookie的儲存

123456789101112131415#!/usr/bin/env/python
#encoding: UTF-8


from urllib import request
from urllib import parse
from http import cookiejar


 
#設定儲存cookie的檔案,同級目錄下的cookie.txt
filename = 'cookie.txt'
#宣告一個MozillaCookieJar物件例項來儲存cookie,之後寫入檔案
cookie = cookiejar.MozillaCookieJar(filename)
#利用urllib庫的HTTPCookieProcessor物件來建立cookie處理器
handler = request.HTTPCookieProcessor(cookie)
#通過handler來構建opener
opener = request.build_opener(handler)
#建立一個請求,原理同urllib2的urlopen
response = opener.open("http://www.baidu.com")
#儲存cookie到檔案
cookie.save(ignore_discard=True, ignore_expires=True)

關於最後save方法的兩個引數在此說明一下:

官方解釋如下:

ignore_discard: save even cookies set to be discarded. 

ignore_expires: save even cookies that have expiredThe file is overwritten if it already exists

由此可見,ignore_discard的意思是即使cookies將被丟棄也將它儲存下來,ignore_expires的意思是如果在該檔案中cookies已經存在,則覆蓋原檔案寫入,在這裡,我們將這兩個全部設定為True。執行之後,cookies將被儲存到cookie.txt檔案中,我們檢視一下內容,附圖如下

QQ截圖20150215215136

使用LWPCookieJar來儲存cookie:

filename ='cookie'

cookie = cookiejar.LWPCookieJar(filename)

使用的時候直接load。

 3)從檔案中獲取Cookie並訪問

那麼我們已經做到把Cookie儲存到檔案中了,如果以後想使用,可以利用下面的方法來讀取cookie並訪問網站,感受一下

1 2 3 4 5 6 7 8 9 10 11 12 13 #!/usr/bin/env/python
#encoding: UTF-8
from urllib import request
from urllib import parse
from http import cookiejar
cookie = cookiejar.MozillaCookieJar()
cookie.load('cookie.txt', ignore_discard=True, ignore_expires=True)
req= request.Request('http://www.baidu.com')
opener = request.build_opener(request.HTTPCookieProcessor(cookie))
response = opener.open(req)
print(response.read())

設想,如果我們的 cookie.txt 檔案中儲存的是某個人登入百度的cookie,那麼我們提取出這個cookie檔案內容,就可以用以上方法模擬這個人的賬號登入百度。

 4)利用cookie模擬網站登入

下面我們以知乎為例,利用cookie實現模擬登入,來感受一下cookie大法吧!

#!/usr/bin/env/python
#encoding: UTF-8

import re
import requests
import http.cookiejar
from PIL import Image
import time
import json

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 '
                         '(KHTML, like Gecko) Chrome/57.0.2987.98 Safari/537.36',
           "Host": "www.zhihu.com",
           "Referer": "https://www.zhihu.com/",
           }
# 建立一個會話,可以把同一使用者的不同請求聯絡起來;直到會話結束都會自動處理cookies
session = requests.Session()
# 建立LWPCookieJar例項,可以存Set-Cookie3型別的檔案。
# 而MozillaCookieJar類是存為'/.txt'格式的檔案
session.cookies = http.cookiejar.LWPCookieJar("cookie")
# 若本地有cookie則不用再post資料了
try:
    session.cookies.load(ignore_discard=True)
except IOError:
    print('Cookie未載入!')


def get_xsrf():
    """
    獲取引數_xsrf
    """
    response = session.get('https://www.zhihu.com', headers=headers)
    html = response.text
    get_xsrf_pattern = re.compile(r'<input type="hidden" name="_xsrf" value="(.*?)"')
    _xsrf = re.findall(get_xsrf_pattern, html)[0]
    return _xsrf


def get_captcha():
    """
    獲取驗證碼本地顯示
    返回你輸入的驗證碼
    """
    t = str(int(time.time() * 1000))
    captcha_url = 'http://www.zhihu.com/captcha.gif?r=' + t + "&type=login"
    response = session.get(captcha_url, headers=headers)
    with open('cptcha.gif', 'wb') as f:
        f.write(response.content)
    # Pillow顯示驗證碼
    im = Image.open('cptcha.gif')
    im.show()
    captcha = input('本次登入需要輸入驗證碼: ')
    return captcha


def login(username, password):
    """
    輸入自己的賬號密碼,模擬登入知乎
    """
    # 檢測到11位數字則是手機登入
    if re.match(r'\d{11}$', username):
        url = 'http://www.zhihu.com/login/phone_num'
        data = {'_xsrf': get_xsrf(),
                'password': password,
                'remember_me': 'true',
                'phone_num': username
                }
    else:
        url = 'https://www.zhihu.com/login/email'
        data = {'_xsrf': get_xsrf(),
                'password': password,
                'remember_me': 'true',
                'email': username
                }
    # 若不用驗證碼,直接登入
    result = session.post(url, data=data, headers=headers)
    # 列印返回的響應,r = 1代表響應失敗,msg裡是失敗的原因
    # loads可以反序列化內建資料型別,而load可以從檔案讀取
    if (json.loads(result.text))["r"] == 1:
        # 要用驗證碼,post後登入
        data['captcha'] = get_captcha()
        result = session.post(url, data=data, headers=headers)
        print((json.loads(result.text))['msg'])
        # 儲存cookie到本地
    session.cookies.save(ignore_discard=True, ignore_expires=True)


def isLogin():
    # 通過檢視使用者個人資訊來判斷是否已經登入
    url = "https://www.zhihu.com/settings/profile"
    # 禁止重定向,否則登入失敗重定向到首頁也是響應200
    login_code = session.get(url, headers=headers, allow_redirects=False).status_code
    if login_code == 200:
        return True
    else:
        return False


if __name__ == '__main__':
    if isLogin():
        print('您已經登入')
    else:
        account = input('輸入賬號:')
        secret = input('輸入密碼:')
        login(account, secret)


以上程式的原理如下

建立一個帶有cookie的opener,在訪問登入的URL時,將登入後的cookie儲存下來,然後利用這個cookie來訪問其他網址。

如登入之後才能檢視的成績查詢呀,本學期課表呀等等網址,模擬登入就這麼實現啦,是不是很酷炫?

好,小夥伴們要加油哦!我們現在可以順利獲取網站資訊了,接下來就是把網站裡面有效內容提取出來,下一節我們去會會正則表示式!