文章目錄
本文涉及的主要內容爲urllib類庫下的request、error、parse模塊
一、介紹
python2中分urllib、urllib2,python3中爲urllib。
Python內置的HTTP請求庫(默認安裝)。
二、四大模塊
- request:打開URL(模擬發送請求,可理解爲輸入瀏覽器輸入網址回車一樣)
- error:異常處理,保證程序不會異常中止
- parse:解析URL(拆分、解析、合併等)
- robotparser:識別網站robots.txt文件
三、實例
3.1 urlopen() 基本請求
3.1.1 抓取網頁源碼【例】
(抓取csdn站點源代碼)
import urllib.request
response = urllib.request.urlopen("https://csdn.net")
print(response.read().decode('utf-8'))
3.1.2 查看返回類型【例】
import urllib.request
response = urllib.request.urlopen("https://csdn.net")
print(type(response))
3.1.3 讀取返回狀態碼【例】
import urllib.request
response = urllib.request.urlopen("https://csdn.net")
print(response.status)
3.1.4 獲取請求頭信息【例】
import urllib.request
response = urllib.request.urlopen("https://csdn.net")
print(response.getheaders())
A data數值傳遞【例】
import urllib.request
import urllib.parse
# 使用data需將bytes()方法將參數轉化成字節流編碼格式內容,第一個參數需要urllib.parse模塊中的urlencode()方法將參數字典轉化成字符串,第二個指定編碼格式
data = bytes(urllib.parse.urlencode({'word':'hello'}),encoding='utf-8')
response = urllib.request.urlopen('http://httpbin.org/post',data=data)
print(response.read())
B timeout超時【例】
(設置超時1s後服務器沒響應拋出異常,該異常屬於urllib.error)
import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)
print(response.read())
a. 超時處理【例】
可以通過超時時間控制網頁長時間未響應時跳出異常,響應超時跳過抓取。(超時處理)
import socket
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('http://httpbin.org/get',timeout=0.1)
# 捕獲URLError異常
except urllib.error.URLError as e:
# 判斷異常時socket.timeout類型(超時異常)
if isinstance(e.reason,socket.timeout):
print('Time Out')
3.2 request請求
3.2.1 抓取網頁源碼【例】
import urllib.request
# 構造數據結構,調用Request類將請求獨立成對象request
request = urllib.request.Request('https://csdn.net')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))
自定義請求頭(request多參數傳遞)【例】
from urllib import request,parse
url = 'http://httpbin.org/post'
headers = {
# 僞裝瀏覽器
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:56.0) Gecko/20100101 Firefox/56.0',
'Host':'httpbin.org'
}
# 定義data數據對象
dict = {
'name':'Germey'
}
# 將data數據轉字節流(bytes()方法和urlencode()方法)
data = bytes(parse.urlencode(dict),encoding='utf-8')
# request多參數構造
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))
3.3 request請求高級用法
3.3.0 Handler介紹
包含各種處理器,專門處理登錄驗證、cookies、代理設置
- urllib.request模塊中的BaseHandler類是其它Handler的父類
(其它各種Handler子類繼承BaseHandler類)
- HTTPRedirectHandler:處理重定向
- HTTPCookieProcessor:處理Cookies
- ProxyHandler:設置代理,默認爲空
- HTTPPasswordMgr:管理密碼,維護用戶名和密碼錶
- HTTPBasicAuthHandler:管理認證(Basic Auth認證問題)
3.3.1 Basic Auth認證頁爬取【例】
(如爬取如下Basic認證頁面,需要輸入用戶名和密碼才能訪問具體網頁)
》》如果正常的爬取該頁面時會報如下錯誤(HTTP狀態碼401,需要授權登錄)
from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
# 定義目標對象信息
username = 'Kevin'
password = '123456'
url = 'http://192.168.226.129/'
# 處理登錄登錄驗證
# 創建密碼管理對象,保存需要處理的用戶名和密碼
p = HTTPPasswordMgrWithDefaultRealm()
# 利用add_password類添加賬戶信息,第一個參數realm是與遠程服務器相關域信息一般都是None(建立處理驗證的Handler)
p.add_password(None, url, username, password)
# 解決認證問題(構建一個HTTP用戶名/密碼驗證的HTTPBasicAuthHandler處理器對象,參數是創建的密碼管理對象)
auth_handler = HTTPBasicAuthHandler(p)
# 利用build_opener()方法構建opener,發送請求時相當於驗證成功
opener = build_opener(auth_handler)
# 處理異常
try:
result = opener.open(url)
html = result.read().decode('utf-8')
# 獲取到的結果就是驗證後的源碼信息
print(html)
# 捕捉錯誤對象
except URLError as e:
# 打印錯誤代碼
print(e.code)
# 打印錯誤原因
print(e.reason)
(認證正確返回認證後的源碼:)
(認證錯誤返回錯誤代碼和原因:)401,需要用戶授權驗證,這裏是用戶名密碼錯誤
Tips:這裏的站點是爲了方便測試自己搭建的,先搭建一個Apache,然後設置訪問認證即可,詳情可參考:LAMP環境搭建、Apache訪問認證
3.3.2 添加使用代理【例】
(本地添加一個代理,運行在9743端口之上)
from urllib.request import ProxyHandler,build_opener
from urllib.error import URLError
# 使用ProxyHandler設置添加代理
proxy_handler = ProxyHandler({
'http':'http://127.0.0.1:9743',
'https':'https://127.0.0.1:9743'
})
# 利用build_opener()方法和Handler構造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)
勾選了自動檢測設置依舊報錯
A CookieJar基礎介紹
使用爬蟲時,會用到Cookie進行模擬登錄訪問,會使用到http.cookiejar庫中的CookieJar來實現,CookieJar有一些子類分別是FileCookieJar,MozillaCookieJar,LWPCookieJar
(一般使用CookieJar(),如果和本地交互使用MozillaCookieJar()或LWPCookieJar() )
- CookieJar:管理HTTP cookie值、存儲HTTP請求生成的Cookie,向傳出的HTTP請求添加cookie對象。整個cookie存儲在內存中,對cookie進行實例垃圾回收後cookie也將丟失
- FileCookieJar(filename, delayload=None, policy=None):CookieJar派生而來,用來創建FileCookieJar實例,檢索Cookie信息並存儲到文件中。(fielname:存儲cookie的文件名;delayload:爲True時支持延時訪問文件,即只有需要時纔讀取文件或在文件中存儲數據)
- MozillaCookieJar(filename, delayload=None, policy=None):FileCookieJar派生而來,創建與Mozilla瀏覽器cookies.txt兼容的FileCookieJar實例。
- LWPCookieJar(filename, delayload=None, policy=None):從FileCookieJar派生來,創建與libwww-perl標準的Set-Cookie3文件格式兼容的FileCookieJar實例
3.3.3 獲取網站cookie【例】
(使用Handler將網站自定義的cookie獲取下來)
import http.cookiejar,urllib.request
from urllib.request import build_opener
# 聲明CookieJar對象,管理存儲HTTP cookie值
cookie = http.cookiejar.CookieJar()
# 處理Cookie
c_handler = urllib.request.HTTPCookieProcessor(cookie)
# 使用build_opener()方法構建opener
opener = build_opener(c_handler)
response = opener.open('https://www.baidu.com')
print(cookie) # 演示理解用
print('\n') # 演示理解用
for item in cookie:
print(item.name+"="+item.value)
(爲了方便理解for循環中自定義的cookie,下面黃框內是未經過處理的Cookie)
3.3.4 生成Mozilla兼容cookie【例】
from urllib.request import HTTPCookieProcessor,build_opener
import http.cookiejar,urllib.request
# 定義保存文件
filename = 'cookies_file.txt'
# 聲明與Mozilla瀏覽器兼容的FileCookieJar實例
cookie = http.cookiejar.MozillaCookieJar(filename)
# 處理cookie
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = build_opener(handler)
response = opener.open('https://www.baidu.com')
# 保存cookie到文件(ignore_discard:即使cookie將要唄丟棄也保存; ignore_expires:即使該文件中的cookie已過期也保存)
cookie.save(ignore_discard=True, ignore_expires=True)
(運行後本地和運行python腳本同級目錄下會生成對應的文件)
3.3.5 生成LWP格式cookie
from urllib.request import HTTPCookieProcessor,build_opener
import http.cookiejar,urllib.request
filename = 'cookies_file.txt'
cookie = http.cookiejar.LWPCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)
3.3.6 讀取使用cookie
》》本地先生成一個LWP格式的cookie文件cookies.txt(代碼如3.6.5)
》》讀取使用本地的cookie去訪問指定站點
import http.cookiejar, urllib.request
from urllib.request import build_opener
# 指定使用讀取LWP格式的cookie文件
cookie = http.cookiejar.LWPCookieJar()
# load()方法讀取本地cookie文件
cookie.load('cookies.txt', ignore_discard=True, ignore_expires=True)
# 構造處理cookie的HTPPCookieProcessor處理器對象對本地cookie進行處理
handler = urllib.request.HTTPCookieProcessor(cookie)
# 構建opener
opener = urllib.request.build_opener(handler)
response = opener.open('https://www.csdn.net')
print(response.read().decode('utf-8'))
》》成功使用本地的cookie讀取指定站點的源代碼
3.4 異常處理
爲了防止程序因報錯而異常終止,urllib的error模塊定義了由request模塊產生的異常。
3.4.1 URLError
urllib庫的error模塊,由request模塊產生的異常都可以由這個捕獲這個類來處理。
from urllib import request,error
try:
# 打開一個不存在的頁面
response = request.urlopen('https://csdn.net/1')
except error.URLError as e:
print(e.reason)
3.4.2 HTTPError
URLError的子類,專門處理HTTP請求錯誤,如認證請求失敗等。
三個屬性
- code:返回HTTP狀態碼
- reason:同父類一樣,返回錯誤原因
- headers:返回請求頭
(捕獲錯誤異常,輸出三個錯誤狀態碼、錯誤原因、返回頭信息)
from urllib import request,error
try:
response = request.urlopen('https://csdn.net/1')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
3.4.3 捕獲子類、父類錯誤
由於HTTPError是URLError的子類,我們可以先捕獲子類錯誤然後再捕獲父類錯誤
(如果不是HTTPError異常就是URLError異常)
from urllib import request,error
try:
response = request.urlopen('https://csdn.net/1')
except error.HTTPError as e:
print(e.reason, e.code, e.headers, sep='\n')
except error.URLError as e:
print(e.reason)
else:
print('Request Successfully')
3.5 解析鏈接
3.5.1 urlparse()(拆解URL)
url識別和分段
from urllib.parse import urlparse
result = urlparse('https://www.baidu.com/index.html;user?id=5#command')
print(type(result), result)
(拆分爲6部分)
- scheme(協議)
- netloc(域名)
- path(訪問路徑)
- params(參數)
- query(查詢條件)
- fragment(錨點)
A URL字段獲取
(用屬性/索引獲取)
3.5.2 urlunparse() (拼接URL)
實現對URL構造,urlunparse()中接收的必須是6位的參數
from urllib.parse import urlunparse
data=['https','www.baidu.com','index.html','user','a=6','']
print(urlunparse(data))
3.5.3 urlsplit()(拆解URL)
拆解URL,返回5個結果,params合併到路徑
from urllib.parse import urlsplit
result = urlsplit('https://www.baidu.com/index.html;user?id=5#command')
print(result,'\n')
# 可以使用屬性或者索引取值
print(result.path)
3.5.4 urlunsplit()(拼接URL)
將鏈接各個部分拼接成完成鏈接
3.5.5 urlencode()(構造URL get請求)
通過字典構造get請求
3.5.6 parse_qs() (提取URL get請求參數-字典)
反序列化get請求參數,轉換爲字典
3.5.7 parse_qsl()(提取URL get請求參數-元組)
反序列化get請求參數,轉換爲字典
3.5.8 quote()(URL編碼)
將內容轉換爲URL編碼的格式