本文地址:http://www.reibang.com/p/f05d33475c78
1. 簡介
urllib
是Python中請求url連接的官方標(biāo)準(zhǔn)庫绑榴,在Python2中主要為urllib和urllib2洁桌,在Python3中整合成了urllib。
而urllib3則是增加了連接池等功能叹谁,兩者互相都有補(bǔ)充的部分座韵。
2. urllib
urllib作為Python的標(biāo)準(zhǔn)庫换薄,基本上涵蓋了基礎(chǔ)的網(wǎng)絡(luò)請求功能暮刃。
2.1. urllib.request
urllib中,request
這個模塊主要負(fù)責(zé)構(gòu)造和發(fā)起網(wǎng)絡(luò)請求帆疟,并在其中加入Headers鹉究、Proxy等。
2.1.1. 發(fā)起GET請求
主要使用urlopen()
方法來發(fā)起請求:
from urllib import request
resp = request.urlopen('http://www.baidu.com')
print(resp.read().decode())
在urlopen()
方法中傳入字符串格式的url地址踪宠,則此方法會訪問目標(biāo)網(wǎng)址自赔,然后返回訪問的結(jié)果。
訪問的結(jié)果會是一個http.client.HTTPResponse
對象殴蓬,使用此對象的read()
方法匿级,則可以獲取訪問網(wǎng)頁獲得的數(shù)據(jù)。但是要注意的是染厅,獲得的數(shù)據(jù)會是bytes
的二進(jìn)制格式痘绎,所以需要decode()
一下,轉(zhuǎn)換成字符串格式肖粮。
2.1.2. 發(fā)起POST請求
urlopen()
默認(rèn)的訪問方式是GET孤页,當(dāng)在urlopen()
方法中傳入data參數(shù)時(shí),則會發(fā)起POST請求涩馆。注意:傳遞的data數(shù)據(jù)需要為bytes格式行施。
設(shè)置timeout參數(shù)還可以設(shè)置超時(shí)時(shí)間允坚,如果請求時(shí)間超出,那么就會拋出異常蛾号。
from urllib import request
resp = request.urlopen('http://httpbin.org/post', data=b'word=hello', timeout=10)
print(resp.read().decode())
2.1.3. 添加Headers
通過urllib
發(fā)起的請求會有默認(rèn)的一個Headers:"User-Agent":"Python-urllib/3.6"稠项,指明請求是由urllib
發(fā)送的。
所以遇到一些驗(yàn)證User-Agent的網(wǎng)站時(shí)鲜结,我們需要自定義Headers展运,而這需要借助于urllib.request中的Request
對象。
from urllib import request
url = 'http://httpbin.org/get'
headers = {'user-agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.181 Safari/537.36'}
# 需要使用url和headers生成一個Request對象精刷,然后將其傳入urlopen方法中
req = request.Request(url, headers=headers)
resp = request.urlopen(req)
print(resp.read().decode())
2.1.4. Request對象
如上所示拗胜,urlopen()
方法中不止可以傳入字符串格式的url,也可以傳入一個Request
對象來擴(kuò)展功能怒允,Request
對象如下所示埂软。
class urllib.request.Request(url, data=None, headers={},
origin_req_host=None,
unverifiable=False, method=None)
構(gòu)造Request
對象必須傳入url參數(shù),data數(shù)據(jù)和headers都是可選的纫事。
最后勘畔,Request
方法可以使用method參數(shù)來自由選擇請求的方法,如PUT儿礼,DELETE等等咖杂,默認(rèn)為GET庆寺。
2.1.5. 添加Cookie
為了在請求時(shí)能帶上Cookie信息蚊夫,我們需要重新構(gòu)造一個opener。
使用request.build_opener方法來進(jìn)行構(gòu)造opener懦尝,將我們想要傳遞的cookie配置到opener中知纷,然后使用這個opener的open方法來發(fā)起請求。
from http import cookiejar
from urllib import request
url = 'https://www.baidu.com'
# 創(chuàng)建一個cookiejar對象
cookie = cookiejar.CookieJar()
# 使用HTTPCookieProcessor創(chuàng)建cookie處理器
cookies = request.HTTPCookieProcessor(cookie)
# 并以它為參數(shù)創(chuàng)建Opener對象
opener = request.build_opener(cookies)
# 使用這個opener來發(fā)起請求
resp = opener.open(url)
# 查看之前的cookie對象陵霉,則可以看到訪問百度獲得的cookie
for i in cookie:
print(i)
或者也可以把這個生成的opener使用install_opener方法來設(shè)置為全局的琅轧。
則之后使用urlopen方法發(fā)起請求時(shí),都會帶上這個cookie踊挠。
# 將這個opener設(shè)置為全局的opener
request.install_opener(opener)
resp = request.urlopen(url)
2.1.6. 設(shè)置Proxy代理
使用爬蟲來爬取數(shù)據(jù)的時(shí)候乍桂,常常需要使用代理來隱藏我們的真實(shí)IP。
from urllib import request
url = 'http://httpbin.org/ip'
proxy = {'http':'218.18.232.26:80','https':'218.18.232.26:80'}
# 創(chuàng)建代理處理器
proxies = request.ProxyHandler(proxy)
# 創(chuàng)建opener對象
opener = request.build_opener(proxies)
resp = opener.open(url)
print(resp.read().decode())
2.1.7. 下載數(shù)據(jù)到本地
在我們進(jìn)行網(wǎng)絡(luò)請求時(shí)常常需要保存圖片或音頻等數(shù)據(jù)到本地效床,一種方法是使用python的文件操作睹酌,將read()獲取的數(shù)據(jù)保存到文件中。
而urllib
提供了一個urlretrieve()
方法剩檀,可以簡單的直接將請求獲取的數(shù)據(jù)保存成文件憋沿。
from urllib import request
url = 'http://python.org/'
request.urlretrieve(url, 'python.html')
urlretrieve()
方法傳入的第二個參數(shù)為文件保存的位置,以及文件名沪猴。
注:urlretrieve()
方法是python2直接移植過來的方法辐啄,以后有可能在某個版本中棄用采章。
2.2. urllib.response
在使用urlopen()
方法或者opener的open()
方法發(fā)起請求后,獲得的結(jié)果是一個response
對象壶辜。
這個對象有一些方法和屬性悯舟,可以讓我們對請求返回的結(jié)果進(jìn)行一些處理。
-
read()
獲取響應(yīng)返回的數(shù)據(jù)砸民,只能使用一次图谷。
-
getcode()
獲取服務(wù)器返回的狀態(tài)碼。
-
getheaders()
獲取返回響應(yīng)的響應(yīng)報(bào)頭阱洪。
-
geturl()
獲取訪問的url便贵。
2.3. urllib.parse
urllib.parse
是urllib中用來解析各種數(shù)據(jù)格式的模塊。
2.3.1. urllib.parse.quote
在url中冗荸,是只能使用ASCII中包含的字符的承璃,也就是說,ASCII不包含的特殊字符蚌本,以及中文等字符都是不可以在url中使用的盔粹。而我們有時(shí)候又有將中文字符加入到url中的需求,例如百度的搜索地址:
https://www.baidu.com/s?wd=南北
程癌?之后的wd參數(shù)舷嗡,則是我們搜索的關(guān)鍵詞。那么我們實(shí)現(xiàn)的方法就是將特殊字符進(jìn)行url編碼嵌莉,轉(zhuǎn)換成可以url可以傳輸?shù)母袷浇眩瑄rllib中可以使用quote()
方法來實(shí)現(xiàn)這個功能。
>>> from urllib import parse
>>> keyword = '南北'
>>> parse.quote(keyword)
'%E5%8D%97%E5%8C%97'
如果需要將編碼后的數(shù)據(jù)轉(zhuǎn)換回來锐峭,可以使用unquote()
方法中鼠。
>>> parse.unquote('%E5%8D%97%E5%8C%97')
'南北'
2.3.2. urllib.parse.urlencode
在訪問url時(shí),我們常常需要傳遞很多的url參數(shù)沿癞,而如果用字符串的方法去拼接url的話援雇,會比較麻煩,所以urllib
中提供了urlencode
這個方法來拼接url參數(shù)椎扬。
>>> from urllib import parse
>>> params = {'wd': '南北', 'code': '1', 'height': '188'}
>>> parse.urlencode(params)
'wd=%E5%8D%97%E5%8C%97&code=1&height=188'
2.4. urllib.error
在urllib
中主要設(shè)置了兩個異常惫搏,一個是URLError
,一個是HTTPError
蚕涤,HTTPError
是URLError
的子類筐赔。
HTTPError
還包含了三個屬性:
- code:請求的狀態(tài)碼
- reason:錯誤的原因
- headers:響應(yīng)的報(bào)頭
例子:
In [1]: from urllib.error import HTTPError
In [2]: try:
...: request.urlopen('http://www.reibang.com')
...: except HTTPError as e:
...: print(e.code)
403
3. urllib3
Urllib3是一個功能強(qiáng)大,條理清晰钻趋,用于HTTP客戶端的Python庫川陆。許多Python的原生系統(tǒng)已經(jīng)開始使用urllib3。Urllib3提供了很多python標(biāo)準(zhǔn)庫urllib里所沒有的重要特性:
- 線程安全
- 連接池
- 客戶端SSL/TLS驗(yàn)證
- 文件分部編碼上傳
- 協(xié)助處理重復(fù)請求和HTTP重定位
- 支持壓縮編碼
- 支持HTTP和SOCKS代理
3.1. 安裝
urllib3是一個第三方庫,安裝非常簡單较沪,pip安裝即可:
pip install urllib3
3.2. 使用
urllib3
主要使用連接池進(jìn)行網(wǎng)絡(luò)請求的訪問鳞绕,所以訪問之前我們需要創(chuàng)建一個連接池對象,如下所示:
>>> import urllib3
>>> http = urllib3.PoolManager()
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.status
200
>>> r.data
'User-agent: *\nDisallow: /deny\n'
3.2.1. 設(shè)置headers
headers={'X-Something': 'value'}
resp = http.request('GET', 'http://httpbin.org/headers', headers=headers)
3.2.2. 設(shè)置url參數(shù)
對于GET等沒有請求正文的請求方法尸曼,可以簡單的通過設(shè)置fields
參數(shù)來設(shè)置url參數(shù)们何。
fields = {'arg': 'value'}
resp = http.request('GET', 'http://httpbin.org/get', fields=fields)
如果使用的是POST等方法,則會將fields作為請求的請求正文發(fā)送控轿。
所以冤竹,如果你的POST請求是需要url參數(shù)的話,那么需要自己對url進(jìn)行拼接茬射。
fields = {'arg': 'value'}
resp = http.request('POST', 'http://httpbin.org/get', fields=fields)
3.2.3. 設(shè)置代理
>>> import urllib3
>>> proxy = urllib3.ProxyManager('http://50.233.137.33:80', headers={'connection': 'keep-alive'})
>>> resp = proxy.request('get', 'http://httpbin.org/ip')
>>> resp.status
200
>>> resp.data
b'{"origin":"50.233.136.254"}\n'
注:urllib3
中沒有直接設(shè)置cookies的方法和參數(shù)鹦蠕,只能將cookies設(shè)置到headers中