Python網(wǎng)絡(luò)請求urllib和urllib3詳解

本文地址: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蚕涤,HTTPErrorURLError的子類筐赔。

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里所沒有的重要特性:

  1. 線程安全
  2. 連接池
  3. 客戶端SSL/TLS驗(yàn)證
  4. 文件分部編碼上傳
  5. 協(xié)助處理重復(fù)請求和HTTP重定位
  6. 支持壓縮編碼
  7. 支持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中

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市在抛,隨后出現(xiàn)的幾起案子钟病,更是在濱河造成了極大的恐慌,老刑警劉巖刚梭,帶你破解...
    沈念sama閱讀 216,692評論 6 501
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件肠阱,死亡現(xiàn)場離奇詭異藏雏,居然都是意外死亡巡语,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,482評論 3 392
  • 文/潘曉璐 我一進(jìn)店門沐旨,熙熙樓的掌柜王于貴愁眉苦臉地迎上來衅金,“玉大人噪伊,你說我怎么就攤上這事〉涮簦” “怎么了酥宴?”我有些...
    開封第一講書人閱讀 162,995評論 0 353
  • 文/不壞的土叔 我叫張陵啦吧,是天一觀的道長您觉。 經(jīng)常有香客問我,道長授滓,這世上最難降的妖魔是什么琳水? 我笑而不...
    開封第一講書人閱讀 58,223評論 1 292
  • 正文 為了忘掉前任,我火速辦了婚禮般堆,結(jié)果婚禮上在孝,老公的妹妹穿的比我還像新娘。我一直安慰自己淮摔,他們只是感情好私沮,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,245評論 6 388
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著和橙,像睡著了一般仔燕。 火紅的嫁衣襯著肌膚如雪造垛。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,208評論 1 299
  • 那天晰搀,我揣著相機(jī)與錄音五辽,去河邊找鬼。 笑死外恕,一個胖子當(dāng)著我的面吹牛杆逗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播鳞疲,決...
    沈念sama閱讀 40,091評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼罪郊,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了尚洽?” 一聲冷哼從身側(cè)響起排龄,我...
    開封第一講書人閱讀 38,929評論 0 274
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎翎朱,沒想到半個月后橄维,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,346評論 1 311
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡拴曲,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,570評論 2 333
  • 正文 我和宋清朗相戀三年争舞,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片澈灼。...
    茶點(diǎn)故事閱讀 39,739評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡竞川,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出叁熔,到底是詐尸還是另有隱情委乌,我是刑警寧澤,帶...
    沈念sama閱讀 35,437評論 5 344
  • 正文 年R本政府宣布荣回,位于F島的核電站遭贸,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏心软。R本人自食惡果不足惜壕吹,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,037評論 3 326
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望删铃。 院中可真熱鬧耳贬,春花似錦、人聲如沸猎唁。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,677評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至腐魂,卻和暖如春慕的,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背挤渔。 一陣腳步聲響...
    開封第一講書人閱讀 32,833評論 1 269
  • 我被黑心中介騙來泰國打工肮街, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人判导。 一個月前我還...
    沈念sama閱讀 47,760評論 2 369
  • 正文 我出身青樓嫉父,卻偏偏與公主長得像,于是被迫代替她去往敵國和親眼刃。 傳聞我的和親對象是個殘疾皇子绕辖,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,647評論 2 354