1. 程式人生 > >urllib.request模板的高階用法

urllib.request模板的高階用法

一 urllib.request的各種Handler

Handler簡而言之,我們可以把它理解為各種處理器,有專門處理登入驗證的,有處理Cookies的,有處理代理設定的。利用它們,我們幾乎可以做到HTTP請求中所有的事情。

首先,介紹一下urllib.request模組裡的BaseHandler類,它是所有其他Handler的父類,它提供了最基本的方法,例如default_open()、protocol_request()等。各種Handler子類繼承這個BaseHandler類。

  • HTTPDefaultErrorHandler:用於處理HTTP響應錯誤,錯誤都會丟擲HTTPError型別的異常。

  • HTTPRedirectHandler:用於處理重定向。

  • HTTPCookieProcessor:用於處理Cookies。

  • ProxyHandler:用於設定代理,預設代理為空。

  • HTTPPasswordMgr:用於管理密碼,它維護了使用者名稱和密碼的表。

  • HTTPBasicAuthHandler:用於管理認證,如果一個連結開啟時需要認證,那麼可以用它來解決認證問題。

二 OpenerDirector介紹

OpenerDirector,我們可以稱為Opener。我們之前用過urlopen()這個方法,實際上它就是urllib為我們提供的一個Opener。

那麼,為什麼要引入Opener呢?因為需要實現更高階的功能。之前使用的Request和urlopen()相當於類庫為你封裝好了極其常用的請求方法,利用它們可以完成基本的請求,但是現在不一樣了,我們需要實現更高階的功能,所以需要深入一層進行配置,使用更底層的例項來完成操作,所以這裡就用到了Opener。

Opener可以使用open()方法,返回的型別和urlopen()如出一轍。那麼,它和Handler有什麼關係呢?簡而言之,就是利用Handler來構建Opener。

三 驗證

1 場景

有些網站在開啟時就會彈出提示框,直接提示你輸入使用者名稱和密碼,驗證成功後才能檢視頁面,例如:

2 程式碼舉例

from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, build_opener
from urllib.error import URLError

username = 'username'
password = 'password'
url = 'http://localhost:8000/account/my-information/'

p = HTTPPasswordMgrWithDefaultRealm()
p.add_password(None, url, username, password)
# 這裡首先例項化HTTPBasicAuthHandler物件,其引數是HTTPPasswordMgrWithDefaultRealm物件,
# 它利用add_password()新增進去使用者名稱和密碼,這樣就建立了一個處理驗證的Handler。
auth_handler = HTTPBasicAuthHandler(p)
# 利用這個Handler並使用build_opener()方法構建一個Opener,這個Opener在傳送請求時就相當於已經驗證成功了。
opener = build_opener(auth_handler)

try:
    # 利用Opener的open()方法開啟連結,就可以完成驗證了。這裡獲取到的結果就是驗證後的頁面原始碼內容。
    result = opener.open(url)
    html = result.read().decode('utf-8')
    print(html)
except URLError as e:
    print(e.reason)

四 代理

1 點睛

在做爬蟲的時候,免不了要使用代理,如果要新增代理,可以像下面這樣做。

2 程式碼

from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener

# 這裡使用了ProxyHandler,其引數是一個字典,
# 鍵名是協議型別(比如HTTP或者HTTPS等),鍵值是代理連結,可以新增多個代理。
proxy_handler = ProxyHandler({
    # 這裡我們在本地搭建了一個代理,它執行在8000埠上
    'http': 'http://127.0.0.1:8000',
    'https': 'https://127.0.0.1:8000'
})
# 利用這個Handler及build_opener()方法構造一個Opener,之後傳送請求即可
opener = build_opener(proxy_handler)
try:
    response = opener.open('https://www.baidu.com')
    print(response.read().decode('utf-8'))
except URLError as e:
    print(e.reason)

五 Cookies

1 獲取網站Cookies

1.1 程式碼

import http.cookiejar, urllib.request
# 必須宣告一個CookieJar物件。
cookie = http.cookiejar.CookieJar()
# 利用HTTPCookieProcessor來構建一個Handler
handler = urllib.request.HTTPCookieProcessor(cookie)
# 利用build_opener()方法構建出Opener
opener = urllib.request.build_opener(handler)
# 執行open()函式即可
response = opener.open('http://www.baidu.com')
for item in cookie:
    print(item.name + "=" + item.value)

1.2 執行結果

E:\WebSpider\venv\Scripts\python.exe E:/WebSpider/3_1_1.py
BAIDUID=80E7B05274F7644E00E3FA0142947F25:FG=1
BIDUPSID=80E7B05274F7644E00E3FA0142947F25
H_PS_PSSID=1454_21089_28205_28132_28267_28139
PSTM=1546766806
delPer=0
BDSVRTM=0
BD_HOME=0

2 將Cookies儲存成文字

2.1 程式碼

import http.cookiejar, urllib.request
filename = 'cookies.txt'
# 這時CookieJar就需要換成MozillaCookieJar,它在生成檔案時會用到,是CookieJar的子類,
# 可以用來處理Cookies和檔案相關的事件,比如讀取和儲存Cookies,可以將Cookies儲存成Mozilla型瀏覽器的Cookies格式。
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)

2.2 生成檔案內容如下

# Netscape HTTP Cookie File
# http://curl.haxx.se/rfc/cookie_spec.html
# This is a generated file!  Do not edit.

.baidu.com    TRUE    /    FALSE    3694250720    BAIDUID    18FC099E164E6C0B70DA82B6B1BB27F1:FG=1
.baidu.com    TRUE    /    FALSE    3694250720    BIDUPSID    18FC099E164E6C0B70DA82B6B1BB27F1
.baidu.com    TRUE    /    FALSE        H_PS_PSSID    1426_21125_28205_28132_26350_28267_28139
.baidu.com    TRUE    /    FALSE    3694250720    PSTM    1546767074
.baidu.com    TRUE    /    FALSE        delPer    0
www.baidu.com    FALSE    /    FALSE        BDSVRTM    0
www.baidu.com    FALSE    /    FALSE        BD_HOME    0

3 將Cookies儲存成LWP格式

3.1 程式碼

import http.cookiejar, urllib.request
filename = 'cookies1.txt'
# 檔案儲存成LWP格式的Cookies檔案
cookie = http.cookiejar.LWPCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)

3.2 生成檔案內容如下

#LWP-Cookies-2.0
Set-Cookie3: BAIDUID="09D84C55FF9E09D21860188E0987C4AD:FG=1"; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2087-01-24 12:49:12Z"; version=0
Set-Cookie3: BIDUPSID=09D84C55FF9E09D21860188E0987C4AD; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2087-01-24 12:49:12Z"; version=0
Set-Cookie3: H_PS_PSSID=1425_21106_18560_28206_28132_26350_28266_28140_27509; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: PSTM=1546767306; path="/"; domain=".baidu.com"; path_spec; domain_dot; expires="2087-01-24 12:49:12Z"; version=0
Set-Cookie3: delPer=0; path="/"; domain=".baidu.com"; path_spec; domain_dot; discard; version=0
Set-Cookie3: BDSVRTM=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0
Set-Cookie3: BD_HOME=0; path="/"; domain="www.baidu.com"; path_spec; discard; version=0

4 利用生成了Cookies檔案

import http.cookiejar, urllib.request
cookie = http.cookiejar.LWPCookieJar()
# 這裡呼叫load()方法來讀取本地的Cookies檔案,
# 獲取到了Cookies的內容。不過前提是我們首先生成了LWPCookieJar格式的Cookies,
# 並儲存成檔案,然後讀取Cookies之後使用同樣的方法構建Handler和Opener即可完成操作。
cookie.load('cookies1.txt', ignore_discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
# 執行結果正常的話,會輸出百度網頁的原始碼。
print(response.read().decode('utf-8'))