注:urllib2
,這個包是基於python2的,官方已經對python2停止更新了並且不再免費,我覺得這個urllib2沒必要再學習和使用
urllib 這個是python的標準庫,在python3裏整合了python2的urllib和urllib2,有時間的可以學習一下。
urllib3,這個是第三方庫,是對第二種方式urllib的升級,做了很多改善,有時間可以學習一下。
requests,各種請求的方法非常的優雅和人性化,其底層是urllib3,簡化headers、proxy、cookie等的操作。這個重點學習。
一、簡介
urllib
是Python中請求url連接的官方標準庫,在Python2中主要爲urllib和urllib2,在Python3中整合成了urllib。基本上涵蓋了基礎的網絡請求功能。
該庫有四個模塊
- urllib.request 發送http請求
- urllib.error 處理請求過程中,出現的異常。
- urllib.parse 解析url
- urllib.robotparser 解析robots.txt 文件
常見三種形式:
import urllib.request
import urllib.parse
from http import cookiejar
'''方法1'''
response = urllib.request.urlopen('www.baidu.com')
print(response.getcode) # 獲取狀態碼
cont = response.read() # 讀取內容
'''方法2,add info.'''
# create Request target
request = urllib.request.Request(url)
request.add_data('a', '1') # 添加數據
request.add_header('User-Agent', 'Mozilla/5.0') # 添加頭文件
response = urllib.request.urlopen(request) # 獲取結果
'''方法3,add handler,cookielib庫
HTTPCookieProcessor 賬號密碼
ProxyHandler 代理
HTTPSHandler 加密訪問
HTTPRedirectHandler 相互自動跳轉關係
'''
cj = cookiejar.CookieJar() # create cookie container
handler = urllib.request.HTTPCookieProcessor(cj) # create a opener
opener = urllib.request.build_opener(handler) # create target
urllib.request.install_opener(opener) # install opener into request
response = urllib.request.urlopen(request) # 同2
二、請求方式
1、get請求
#第一步導包
from urllib import request
url = "http://httpbin.org"
#第二步請求
response = request.urlopen(url,timeout=1)
#第三步打印返回數據
print(response.read().decode())
訪問的結果會是一個http.client.HTTPResponse
對象,使用此對象的read()
方法,則可以獲取訪問網頁獲得的數據。但是要注意的是,獲得的數據會是bytes
的二進制格式,所以需要decode()
一下,轉換成字符串格式。
urlopen()
urllib發送請求是用urlopen()
源碼如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
- 第一個參數 String 類型的地址
data
是 bytes 類型的內容,可通過bytes()
函數或者encode()
轉爲化字節流。它也是可選參數。使用data
參數,請求方式變成以POST
方式提交表單。使用標準格式是application/x-www-form-urlencoded
-
timeout
參數是用於設置請求超時時間。單位是秒。 cafile
和capath
代表 CA 證書和 CA 證書的路徑。如果使用HTTPS則需要用到。context
參數必須是ssl.SSLContext類型,用來指定SSL設置cadefault
參數已經被棄用,可以不用管了。- 該方法也可以單獨傳入
urllib.request.Request
對象 - 該函數返回結果是一個
http.client.HTTPResponse
對象。
http.client.HTTPResponse
對象。它具有msg
、version
、status
、reason
、debuglevel
、closed
等屬性以及read()
、readinto()
、getheader(name)
、getheaders()
、fileno()
等函數。
# print(response.msg) # OK
# print(response.version) #11
# print(response.status) #200
# print(response.reason) #OK
# print(response.getcode()) #200
# print(response.getheaders) # <bound method HTTPResponse.getheaders of <http.client.HTTPResponse object at 0x0000023C554DB588>>
# print(response.geturl()) #http://httpbin.org/headers
2、post請求
from urllib import request,parse
url = "http://httpbin.org"
data = {
'name':'xfy'
}
# data = bytes(parse.urlencode(data),encoding='utf8');
data = parse.urlencode(data).encode()
response = request.urlopen(url+"/post",data=data)
print(response.status) #200
print(response.read().decode())
data
需要被轉碼成字節流。而data
是一個字典。我們需要使用 parse.urlencode()
將字典轉化爲字符串。再使用 bytes()或者encode() 轉爲字節流。最後使用 urlopen()
發起請求,請求是模擬用 POST 方式提交表單數據。
這裏說一下http://httpbin.org
,這個url專門是用來爬蟲請求測試的。
http://httpbin.org/get 測試get請求
http://httpbin.org/post 測試post請求
http://httpbin.org/headers 測試獲得headers
http://httpbin.org/ip 測試獲得ip
http://httpbin.org/cookies 測試獲得cookies
三、創建 Request 對象
urlopen()還可以傳一個Request對象
req = request.Request(url+"/get")
response = request.urlopen(req)
print(response.read().decode())
urllib/request 包下有一個類Request
其初始化方法如下
def __init__(self, url, data=None, headers={},
origin_req_host=None, unverifiable=False,
method=None):
url
參數是請求鏈接,這個是必傳參數,其他的都是可選參數。data
參數跟 urlopen() 中的 data 參數用法相同。沒有addd_dataheaders
參數是指定發起的 HTTP 請求的頭部信息。headers 是一個字典。
它除了在 Request 中添加,還可以通過調用 Reques t實例的 add_header() 方法來添加請求頭。
origin_req_host
參數指的是請求方的 host 名稱或者 IP 地址。unverifiable
參數表示這個請求是否是無法驗證的,默認值是False。意思就是說用戶沒有足夠權限來選擇接收這個請求的結果。例如我們請求一個HTML文檔中的圖片,但是我們沒有自動抓取圖像的權限,我們就要將 unverifiable 的值設置成 True。method
參數指的是發起的 HTTP 請求的方式,有 GET、POST、DELETE、PUT等
四、設置headers 模擬瀏覽器
通過urllib
發起的請求會有默認的一個Headers:"User-Agent":"Python-urllib/3.6"
,指明請求是由urllib
發送的。
所以遇到一些驗證User-Agent的網站時,我們需要自定義Headers
,而這需要藉助於urllib.request
中的Request
對象。
headers = {
'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'
}
req = request.Request(url+"/headers",headers=headers)
response = request.urlopen(req)
print(response.read().decode())
五、Request的高端使用
如果我們需要在請求中添加代理、處理請求的 Cookies,我們需要用到Handler和OpenerDirector。
-
Handler
Handler 的中文意思是處理者、處理器。 Handler 能處理請求(HTTP、HTTPS、FTP等)中的各種事情。它的具體實現是這個類 urllib.request.BaseHandler。它是所有的 Handler 的基類,其提供了最基本的Handler的方法,例如default_open()、protocol_request()等。
繼承 BaseHandler 有很多個,我就列舉幾個比較常見的類:
- ProxyHandler:爲請求設置代理
- HTTPCookieProcessor:處理 HTTP 請求中的 Cookies
- HTTPDefaultErrorHandler:處理 HTTP 響應錯誤。
- HTTPRedirectHandler:處理 HTTP 重定向。
- HTTPPasswordMgr:用於管理密碼,它維護了用戶名密碼的表。
- HTTPBasicAuthHandler:用於登錄認證,一般和 HTTPPasswordMgr 結合使用。
-
OpenerDirector
對於 OpenerDirector
,我們可以稱之爲 Opener
。我們之前用過 urlopen() 這個方法,實際上它就是 urllib 爲我們提供的一個Opener
。那Opener
和 Handler
又有什麼關係?
opener
對象是由build_opener(handler)
方法來創建出來。- 我們需要創建自定義的
opener
,就需要使用install_opener(opener)
方法。 - 值得注意的是,
install_opener
實例化會得到一個全局的OpenerDirector
對象。
1、使用代理
有些網站做了瀏覽頻率限制。如果我們請求該網站頻率過高。該網站會被封IP,禁止我們的訪問。所以我們需要使用代理來突破這“枷鎖”。
proxy_header = request.ProxyHandler({
'http':'101.236.19.165:8866'
})
opener = request.build_opener(proxy_header)
request.install_opener(opener)
response = request.urlopen(url+"/ip")
print(response.read().decode())
#打印結果
{"origin":"101.236.19.165"}
2、cookie的設置
如果請求的頁面每次需要身份驗證,我們可以使用 Cookies 來自動登錄,免去重複登錄驗證的操作。獲取 Cookies 需要使用http.cookiejar.CookieJar()
實例化一個Cookies對象。再用rllib.request.HTTPCookieProcessor
構建出handler對象。最後使用 opener 的 open()函數即可。
import http.cookiejar
# 創建一個cookiejar對象
cookie = http.cookiejar.CookieJar()
# 使用HTTPCookieProcessor創建handler處理器
handler = request.HTTPCookieProcessor(cookie)
# 並以它爲參數創建Opener對象
opener = request.build_opener(handler)
# 使用這個opener來發起請求
response = opener.urlopen("https://blog.csdn.net/keep_learn/article/details/68124190")
for item in cookie:
print(item.name)
print(item.value)
打印結果
dc_session_id
10_1531039395672.102673
uuid_tt_dd
10_19936141720-1531039395672-826694
六、請求異常處理
發起請求難免會出現各種異常,我們需要對異常進行處理,這樣會使得程序比較人性化。
異常處理主要用到兩個類,urllib.error.URLError
和urllib.error.HTTPError
。
-
URLError
URLError
是urllib.error
異常類的基類, 可以捕獲由urllib.request
產生的異常。它具有一個屬性reason
,即返回錯誤的原因。
from urllib import request,error
data = {
'name':'xfy'
}
data = parse.urlencode(data).encode()
try:
response = request.urlopen(url,data=data)
except error.URLError as e:
print(e.reason)
打印
METHOD NOT ALLOWED
-
HTTPError
HTTPError
是UEKRrror
的子類,專門處理 HTTP 和 HTTPS 請求的錯誤。它具有三個屬性。
code
:HTTP 請求返回的狀態碼。renson
:與父類用法一樣,表示返回錯誤的原因。headers
:HTTP 請求返回的響應頭信息。
from urllib import request,error
data = {
'name':'xfy'
}
data = parse.urlencode(data).encode()
from urllib import error
try:
response = request.urlopen(url,data=data)
except error.HTTPError as e:
print(e.reason)
print(e.code)
print(e.headers)
打印:
METHOD NOT ALLOWED
405
Connection: close
Server: gunicorn/19.8.1
Date: Sun, 08 Jul 2018 08:57:40 GMT
Content-Type: text/html
Allow: GET, OPTIONS, HEAD
Content-Length: 178
Access-Control-Allow-Origin: *
Access-Control-Allow-Credentials: true
Via: 1.1 vegur
七、下載數據到本地
在我們進行網絡請求時常常需要保存圖片或音頻等數據到本地,一種方法是使用python的文件操作,將read()獲取的數據保存到文件中。
而urllib
提供了一個urlretrieve()
方法,可以簡單的直接將請求獲取的數據保存成文件。
from urllib import request
url = 'http://python.org/'
request.urlretrieve(url, 'python.html')
urlretrieve()
方法傳入的第二個參數爲文件保存的位置,以及文件名。
注:urlretrieve()
方法是python2直接移植過來的方法,以後有可能在某個版本中棄用。
八、urllib 處理 https 請求ssl 證書驗證(瞭解)
import ssl
#處理HTTPS請求 SSL證書驗證 忽略認證 比如12306 網站
url = "https://www.12306.cn/mormhweb/"
#添加忽略ssl證書驗證
context = ssl._create_unverified_context()
header = headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_0) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11"}
req = request.Request(url, headers=header)
res = request.urlopen(req,context = context)
print(res.read().decode())
九、urllib.parse
urllib.parse
是urllib中用來解析各種數據格式的模塊。
urllib.parse.quote
在url中,是隻能使用ASCII中包含的字符的,也就是說,ASCII不包含的特殊字符,以及中文等字符都是不可以在url中使用的。而我們有時候又有將中文字符加入到url中的需求,例如百度的搜索地址:
https://www.baidu.com/s?wd=周杰倫
?之後的wd參數,則是我們搜索的關鍵詞。那麼我們實現的方法就是將特殊字符進行url編碼,轉換成可以url可以傳輸的格式,urllib中可以使用quote()
方法來實現這個功能。
from urllib import parse
keyword = '周杰倫'
parse.quote(keyword)
%E5%91%A8%E6%9D%B0%E4%BC%A6
如果需要將編碼後的數據轉換回來,可以使用unquote()
方法。
parse.unquote('%E5%91%A8%E6%9D%B0%E4%BC%A6')
'周杰倫'
urllib.parse.urlencode
在訪問url時,我們常常需要傳遞很多的url參數,而如果用字符串的方法去拼接url的話,會比較麻煩,所以urllib
中提供了urlencode
這個方法來拼接url參數。
params = {'query':'徐繁韻','name':'xfy'}
data = parse.urlencode(params)
print(data)
query=%E5%BE%90%E7%B9%81%E9%9F%B5&name=xfy