Python urllib、urllib二、urllib3用法及區別

簡介1

在可供使用的網絡庫中,urlliburllib2多是投入產出比最高的兩個,是Python中操做url的官方標準庫。它們讓你可以經過網絡訪問文件,就像這些文件位於你的計算機中同樣。只需一個簡單的函數調用,就幾乎可將統一資源定位符(URL)可指向的任何動做做爲程序的輸入。結合re模塊使用將發揮強大威力!html

一個簡單的例子:python

req = urllib2.Request(
	url=url,
	data=postdata,
	headers=headers
)
result = urllib2.urlopen(req)

模塊urlliburllib2的功能差很少,簡單來講urllib2urllib的加強——urllib2更好一些,可是urllib中有urllib2中所沒有的函數。對於簡單的下載, urllib綽綽有餘。 若是須要實現HTTP身份驗證Cookie亦或編寫擴展來處理本身的協議,urllib2多是更好的選擇。在Python2.x中主要爲urlliburllib2,這兩個標準庫是不可相互替代的。可是在Python3.x中將urllib2合併到了urllib,這一點值得注意。git

  • urllib支持設置編碼的函數urllib.urlencode,在模擬登錄的時候常常須要傳遞通過post編碼以後的參數,若是不想使用第三方庫完成模擬登陸,就必須使用到標準庫中的urlliburllib提供一些比較原始基礎的方法而urllib2並無,好比urllib中的urlencode方法用來GET查詢字符串的產生。github

  • urllib2比較有優點的地方在於urllib2.openurl中能夠接受一個Request類的實例來設置Request參數,來修改/設置Header頭從而達到控制HTTP Request的header部分的目的,也能夠修改用戶代理,設置cookie等,但urllib僅能夠接受URL。這就意味着,若是你訪問一個網站想更改User Agent(能夠假裝你的瀏覽器),你就須要使用urllib2urllib2模塊沒有加入urllib.urlretrieve函數以及urllib.quote等一系列quote和unquote功能,這個時候就須要urllib的輔助。web

所以Python2.x中,urlliburllib2二者搭配使用。正則表達式

一、打開遠程文件

幾乎能夠像打開本地文件同樣打開遠程文件,差異是隻能使用讀取模式,以及使用模塊urllib.request中的函數urlopen,而不是open(或file)。shell

from urllib.request import urlopen
webpage = urlopen('http://www.python.org')

若是鏈接到了網絡,變量webpage將包含一個相似於文件的對象,這個對象與網頁http://www.python.org相關聯。json

注意:要在沒有聯網的狀況下嘗試使用模塊urllib,可以使用以file:打頭的URL訪問本地文件,如file:c:\text\somefile.txt(別忘了對反斜槓進行轉義)。瀏覽器

urlopen返回的相似於文件的對象支持方法:close、 read、readline和readlines,還支持迭代等。安全

假設要提取剛纔所打開網頁中連接About的相對URL, 可以使用正則表達式 。

>>> import re
>>> text = webpage.read()
# 注意:若是這個網頁發生了變化,你可能須要修改使用的正則表達式。
>>> m = re.search(b'<a href="([^"]+)" .*?>about</a>', text, re.IGNORECASE)
>>> m.group(1)
'about'
0二、獲取遠程文件

函數urlopen返回一個相似於文件的對象,可從中讀取數據。若是要讓urllib替你下載文件並將其副本存儲在一個本地文件中,可以使用urlretrieve。這個函數不返回一個相似於文件的對象,而返回一個格式爲(filename, headers)的元組,其中filename是本地文件的名稱(由urllib自動建立),而headers包含一些有關遠程文件的信息(這裏不會介紹headers, 若是你想更深刻地瞭解它,請在有關urllib的標準庫文檔中查找urlretrieve)。若是要給下載的副本指定文件名,可經過第二個參數來提供。

urlretrieve('http://www.python.org', 'C:\\python_webpage.html')

這將獲取Python官網的主頁,並將其存儲到文件C:\python_webpage.html中。若是你沒有指定文件名,下載的副本將放在某個臨時位置,可以使用函數open來打開。但使用完畢後,你可能想將其刪除以避免佔用磁盤空間。要清空這樣的臨時文件,可調用函數urlcleanup且不提供任何參數,它將負責替你完成清空工做。

一些實用的函數

除了經過URL讀取和下載文件外,urllib還提供了一些用於操做URL的函數,以下所示(這裏假設你對URL和CGI略知一二)。

  • quote(string[, safe]) 返回一個字符串,其中全部的特殊字符(在URL中有特殊意義的字符)都已替換爲對URL友好的版本(如將~替換爲%7E),若是要將包含特殊字符的字符串用做URL頗有用。參數safe是一個字符串(默認爲'/'),包含不該像這樣對其進行編碼的字符

  • quote_plus(string[, safe]) 相似於quote,但也將空格替換爲加號。

  • unquote(string):與quote相反。

  • unquote_plus(string):與quote_plus相反。

  • urlencode(query[, doseq]) 將映射(如字典)或由包含兩個元素的元組(形如(key, value))組成的序列轉換爲「使用URL編碼的」字符串。這樣的字符串可用於CGI查詢中(詳細信息請參閱Python文檔)。


1、urllib

urllib做爲Python的標準庫,基本上涵蓋了基礎的網絡請求功能。

1。 urllib.request

urllib中,request這個模塊主要負責構造和發起網絡請求,並在其中加入Headers、Proxy等。

1. 發起GET請求

主要使用urlopen()方法來發起請求:

from urllib import request

resp = request.urlopen('http://www.baidu.com')
print(resp.read().decode())

urlopen()方法中傳入字符串格式的url地址,則此方法會訪問目標網址,而後返回訪問的結果。

返回的結果會是一個http.client.HTTPResponse對象,使用此對象的read()方法能夠獲取訪問網頁得到的數據。可是要注意的是,得到的數據會是bytes的二進制格式,因此須要decode()一下,轉換成字符串格式。

使用帶參數的GET方法取回URL:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query?%s" % params)
>>> print f.read()
2. 發起POST請求

urlopen()默認的訪問方式是GET,當在urlopen()方法中傳入data參數時,則會發起POST請求。注意:傳遞的data數據須要爲bytes格式。timeout參數還能夠設置超時時間若是請求時間超出,那麼就會拋出異常。

from urllib import request

resp = request.urlopen('http://httpbin.org/post', data=b'word=hello', timeout=10)
print(resp.read().decode())

使用帶參數的POST方法:

>>> import urllib
>>> params = urllib.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> f = urllib.urlopen("http://www.musi-cal.com/cgi-bin/query", params)
>>> print f.read()
3. 添加Headers

經過urllib發起的請求會有默認的一個Headers:"User-Agent":"Python-urllib/3.6",指明請求是由urllib發送的。
因此遇到一些驗證User-Agent的網站時,咱們須要自定義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())
4. Request對象

如上所示,urlopen()方法中不止能夠傳入字符串格式的url,也能夠傳入一個Request對象來擴展功能,Request對象以下所示。

class urllib.request.Request(url, data=None, headers={},
                             origin_req_host=None,
                             unverifiable=False, method=None)

構造Request對象必須傳入url參數,data數據和headers都是可選的。
最後,Request方法可使用method參數來自由選擇請求的方法,如PUT,DELETE等等,默認爲GET。

5. 添加Cookie

爲了在請求時能帶上Cookie信息,咱們須要從新構造一個opener。
使用request.build_opener方法來進行構造opener,將咱們想要傳遞的cookie配置到opener中,而後使用這個opener的open方法來發起請求。

from http import cookiejar
from urllib import request

url = 'https://www.baidu.com'

# 建立一個cookiejar對象
cookie = cookiejar.CookieJar()

# 使用HTTPCookieProcessor建立cookie處理器
cookies = request.HTTPCookieProcessor(cookie)

# 並以它爲參數建立Opener對象
opener = request.build_opener(cookies)

# 使用這個opener來發起請求
resp = opener.open(url)

# 查看以前的cookie對象,則能夠看到訪問百度得到的cookie
for i in cookie:
    print(i)

或者也能夠把這個生成的opener使用install_opener方法來設置爲全局的,以後使用urlopen方法發起請求時,都會帶上這個cookie

# 將這個opener設置爲全局的opener
request.install_opener(opener)
resp = request.urlopen(url)
6. 設置Proxy代理

使用爬蟲來爬取數據的時候,經常須要使用代理來隱藏咱們的真實IP。

from urllib import request

url = 'http://httpbin.org/ip'
proxy = {'http':'218.18.232.26:80','https':'218.18.232.26:80'}

# 建立代理處理器
proxies = request.ProxyHandler(proxy)
# 建立opener對象
opener = request.build_opener(proxies)

resp = opener.open(url)
print(resp.read().decode())

urllib官方文檔的例子:

# 使用HTTP代理,自動跟蹤重定向
>>> import urllib
>>> proxies = {'http': 'http://proxy.example.com:8080/'}
>>> opener = urllib.FancyURLopener(proxies)
>>> f = opener.open("http://www.python.org")
>>> f.read()

# 不使用代理
>>> import urllib
>>> opener = urllib.FancyURLopener({})
>>> f = opener.open("http://www.python.org/")
>>> f.read()
7. 下載數據到本地

在咱們進行網絡請求時經常須要保存圖片或音頻等數據到本地,一種方法是使用python的文件操做,將read()獲取的數據保存到文件中。
而urllib提供了一個urlretrieve()方法,能夠簡單的直接將請求獲取的數據保存成文件。

from urllib import request

url = 'http://python.org/'
# urlretrieve()方法傳入的第二個參數爲文件保存的位置,以及文件名。
request.urlretrieve(url, 'python.html')

urlretrieve()方法是Python2.x直接移植過來的方法,之後有可能在某個版本中棄用。

2。urllib.response

在使用urlopen()方法或者opener的open()方法發起請求後,得到的結果是一個response對象。這個對象有一些方法和屬性,可讓咱們對請求返回的結果進行一些處理。

read():獲取響應返回的數據,只能使用一次。

getcode():獲取服務器返回的狀態碼。

getheaders():獲取返回響應的響應報頭。

geturl():獲取訪問的url。

3。urllib.parse

urllib.parseurllib中用來解析各類數據格式的模塊。

1. 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%8D%97%E5%8C%97'

若是須要將編碼後的數據轉換回來,可使用unquote()方法。

>>> parse.unquote('%E5%8D%97%E5%8C%97')
'南北'
2. urllib.parse.urlencode

在訪問url時,咱們經常須要傳遞不少的url參數,而若是用字符串的方法去拼接url的話,會比較麻煩,因此urllib中提供了urlencode這個方法來拼接url參數。

>>> from urllib import parse
>>> params = {'wd': '南北', 'code': '1', 'height': '188'}
>>> parse.urlencode(params)
'wd=%E5%8D%97%E5%8C%97&code=1&height=188'

4。urllib.error

在urllib中主要設置了兩個異常,一個是URLError,一個是HTTPErrorHTTPErrorURLError的子類。

HTTPError還包含了三個屬性:

  • code:請求的狀態碼
  • reason:錯誤的緣由
  • headers:響應的報頭

例子:

In [1]: from urllib.error import HTTPError

In [2]: try:
   ...:     request.urlopen('https://www.jianshu.com')
   ...: except HTTPError as e:
   ...:     print(e.code)

403

2、urllib2

Python2.x的一個例子:

import urllib2
 
# 設置瀏覽器請求頭
ua_headers={
    "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64; rv:34.0) Gecko/20100101 Firefox/34.0"
}

#創建請求內容
request=urllib2.Request("http://baidu.com/",headers=ua_headers)

#獲取響應
response=urllib2.urlopen(request)

#頁面內容
html=response.read()

print html
print response.getcode()	#返回響應碼
print response.geturl()		#返回實際url
print response.info() 		#返回服務器響應的報頭

Python3.x(整合以後的urllib)的一個例子:

from urllib import request

url = r'https://www.baidu.com/'
headers = {
    'User-Agent': r'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) '
                  r'Chrome/45.0.2454.85 Safari/537.36 115Browser/6.0.3',
    'Referer': r'http://www.lagou.com/zhaopin/Python/?labelWords=label',
    'Connection': 'keep-alive'
}
req = request.Request(url, headers=headers)
html = request.urlopen(req).read()

# 處理編碼
html = html.decode('utf-8')
print(html)

來自urllib2官方文檔的幾個例子:

GET一個URL:
>>> import urllib2
>>> f = urllib2.urlopen('http://www.python.org/')
>>> print f.read()
使用基本的HTTP認證:
import urllib2
auth_handler = urllib2.HTTPBasicAuthHandler()
auth_handler.add_password(realm='PDQ Application',
                          uri='https://mahler:8092/site-updates.py',
                          user='klem',
                          passwd='kadidd!ehopper')
opener = urllib2.build_opener(auth_handler)
urllib2.install_opener(opener)
urllib2.urlopen('http://www.example.com/login.html')

注:build_opener()默認提供不少處理程序,包括代理處理程序,代理默認會被設置爲環境變量所提供的。

一個使用代理的例子:
proxy_handler = urllib2.ProxyHandler({'http': 'http://www.example.com:3128/'})
proxy_auth_handler = urllib2.ProxyBasicAuthHandler()
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')

opener = urllib2.build_opener(proxy_handler, proxy_auth_handler)
opener.open('http://www.example.com/login.html')
添加HTTP請求頭部:
import urllib2
req = urllib2.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
r = urllib2.urlopen(req)
更改User-agent:
import urllib2
opener = urllib2.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
opener.open('http://www.example.com/')

注:httplibhttplib2httplib是http客戶端協議的實現,一般不直接使用,urllib是以httplib爲基礎,httplib2是第三方庫,比httplib有更多特性。httplib比較底層,通常使用的話用urlliburllib2便可。

3、Python3.X中使用整合後的urllib

Python2.x 有這些庫名可用: urlliburllib2urllib3httplibhttplib2requests
Python3.x 有這些庫名可用: urlliburllib3httplib2requests


若只使用Python3.x,記住有個urllib的庫就好了。Pyhton2.x和Python3.x都有urllib3requests, 它們不是標準庫。urllib3提供線程安全鏈接池和文件post等支持,與urlliburllib2的關係不大。requests 自稱HTTP for Humans,使用更簡潔方便。

Python3.x中將urllib2合併到了urllib,以後此包分紅了如下幾個模塊:

  • urllib.request 用於打開和讀取URL

  • urllib.error 用於處理前面request引發的異常

  • urllib.parse 用於解析URL

  • urllib.robotparser用於解析robots.txt文件

Python3.x中,隨着urllib2合入urllib,一些經常使用的方法也發生了變化:2

  1. 在Python2.x中使用import urlparse——在Python3.x中會使用import urllib.parse

  2. 在Python2.x中使用urllib2.urlopenurllib.urlopen(已棄用)——在Python3.x中會使用urllib.request.urlopen

  3. 在Python2.x中使用urllib2.Request——在Python3.x中會使用urllib.request.Request

  4. 在Python2.x中使用urllib.quote——在Python3.x中會使用urllib.request.quote

  5. 在Python2.x中使用urllib.urlencode——在Python3.x中會使用urllib.parse.urlencode

  6. 在Python2.x中使用cookielib.CookieJar——在Python3.x中會使用http.CookieJar

  7. 異常處理:在Python2.x中使用urllib2.URLError,urllib2.HTTPError——在Python3.x中會使用urllib.error.URLError,urllib.error.HTTPError

:在Python3.3後urllib2已經不能再用,全部urllib2所有用urllib.request來代替。


urlliburllib2在Python2.x以及Python3.x的區別:

Python2.x中:
import urllib
import urllib2

一、共同點:均可以直接用urlopen(‘url’)請求頁面

二、不一樣點:urlliburlencode(dict)unquote()進行編碼和解碼

三、對於error:

try:
	response = urllib2.urlopen("http://pythonsite.com/111341.html")
except urllib2.HTTPError as e:
	print(e.reason)
	print(e.code)
	print(e.headers)
except urllib2.URLError as e:
	print(e.reason)

else:
	print("reqeust successfully")
Python3.x中:

一、請求頁面:urllib.request.urlopen(‘url’)

二、對於error:

from urllib import request,error
try:
	response = request.urlopen("http://pythonsite.com/113211.html")
except error.HTTPError as e:
	print(e.reason)
	print(e.code)
	print(e.headers)
except error.URLError as e:
	print(e.reason)

else:
	print("reqeust successfully")

幾個官方例子:

GET一個URL:
>>> import urllib.request
>>> with urllib.request.urlopen('http://www.python.org/') as f:
...     print(f.read(300))
PUT一個請求:
import urllib.request
DATA=b'some data'
req = urllib.request.Request(url='http://localhost:8080', data=DATA, method='PUT')
with urllib.request.urlopen(req) as f:
    pass
print(f.status)
print(f.reason)
基本的HTTP認證:
import urllib.request
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm='PDQ Application',
                          uri='https://mahler:8092/site-updates.py',
                          user='klem',
                          passwd='kadidd!ehopper')
opener = urllib.request.build_opener(auth_handler)
urllib.request.install_opener(opener)
urllib.request.urlopen('http://www.example.com/login.html')
使用proxy:
proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
proxy_auth_handler.add_password('realm', 'host', 'username', 'password')

opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
opener.open('http://www.example.com/login.html')
添加頭部:
import urllib.request
req = urllib.request.Request('http://www.example.com/')
req.add_header('Referer', 'http://www.python.org/')
r = urllib.request.urlopen(req)
更改User-agent:
import urllib.request
opener = urllib.request.build_opener()
opener.addheaders = [('User-agent', 'Mozilla/5.0')]
opener.open('http://www.example.com/')
使用GET時設置URL的參數:
>>> import urllib.request
>>> import urllib.parse
>>> params = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> url = "http://www.musi-cal.com/cgi-bin/query?%s" % params
>>> with urllib.request.urlopen(url) as f:
...     print(f.read().decode('utf-8'))
...
使用POST時設置參數:
>>> import urllib.request
>>> import urllib.parse
>>> data = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
>>> data = data.encode('ascii')
>>> with urllib.request.urlopen("http://requestb.in/xrbl82xr", data) as f:
...     print(f.read().decode('utf-8'))
...
指定proxy:
>>> import urllib.request
>>> proxies = {'http': 'http://proxy.example.com:8080/'}
>>> opener = urllib.request.FancyURLopener(proxies)
>>> with opener.open("http://www.python.org") as f:
...     f.read().decode('utf-8')
...
不使用proxy, 覆蓋環境變量的proxy:
>>> import urllib.request
>>> opener = urllib.request.FancyURLopener({})
>>> with opener.open("http://www.python.org/") as f:
...     f.read().decode('utf-8')
...

注:Python2.X中的httplib被重命名爲http.client

使用2to3工具轉換源碼時, 會自動處理這幾個庫的導入.

總的來講, 使用Python3.x, 記住只有urllib, 想要更簡潔好用就用requests, 但不夠通用。


4、urllib33

urllib3功能強大且易於使用,用於HTTP客戶端的Python庫。許多Python的原生系統已經開始使用urllib3

urllib3提供了不少python標準庫urllib裏所沒有的重要特性:

  • 線程安全
  • 鏈接池
  • 客戶端SSL/TLS驗證
  • 文件分部編碼上傳
  • 協助處理重複請求和HTTP重定位
  • 支持gzip和deflate壓縮編碼
  • 支持HTTP和SOCKS代理
  • 100%測試覆蓋率

1。安裝

urllib3是一個第三方庫,pip安裝:

$ pip install urllib3

或者,能夠從GitHub獲取最新的源代碼:

$ git clone git://github.com/shazow/urllib3.git
$ python setup.py install

2。使用

urllib3主要使用鏈接池進行網絡請求的訪問,因此訪問以前須要先建立一個鏈接池對象:

# 導入urllib3模塊:
>>> import urllib3
# 須要一個PoolManager實例來生成請求,由該實例對象處理與線程池的鏈接以及線程安全的全部細節,不須要任何人爲操做:
>>> http = urllib3.PoolManager()
# 經過request()方法建立一個請求,該方法返回一個HTTPResponse對象:
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.status
200
>>> r.data
'User-agent: *\nDisallow: /deny\n'
1.設置headers

經過request()方法向請求(request)中添加一些其餘信息:

>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={'hello': 'world'})

或者:在request()方法中,能夠定義一個字典類型(dictionary),並做爲headers參數傳入:

headers={'X-Something': 'value'}
resp = http.request('GET', 'http://httpbin.org/headers', headers=headers)
2.設置url參數

對於GET等沒有請求正文的請求方法,能夠簡單的經過設置fields參數來設置url參數。

fields = {'arg': 'value'}
resp = http.request('GET', 'http://httpbin.org/get', fields=fields)

若是使用的是POST等方法,則會將fields做爲請求的請求正文發送。
因此,若是你的POST請求是須要url參數的話,那麼須要本身對url進行拼接。

fields = {'arg': 'value'}
resp = http.request('POST', 'http://httpbin.org/get', fields=fields)
3.設置代理
>>> 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中沒有直接設置cookies的方法和參數,只能將cookies設置到headers中。

4.官網的一些介紹

請求(request)中的數據項(request data)可包括:

Headers

在request()方法中,能夠定義一個字典類型(dictionary)並做爲headers參數傳入:

>>> r = http.request(
...     'GET',
...     'http://httpbin.org/headers',
...     headers={
...         'X-Something': 'value'
...     })
>>> json.loads(r.data.decode('utf-8'))['headers']
{'X-Something': 'value', ...}
Query parameters

對於GET、HEAD和DELETE請求,能夠簡單的經過定義一個字典類型做爲fields參數傳入便可:

>>> r = http.request(
...     'GET',
...     'http://httpbin.org/get',
...     fields={'arg': 'value'})
>>> json.loads(r.data.decode('utf-8'))['args']
{'arg': 'value'}

對於POST和PUT請求(request),須要手動對傳入數據進行編碼,而後加在URL以後:

>>> from urllib.parse import urlencode
>>> encoded_args = urlencode({'arg': 'value'})
>>> url = 'http://httpbin.org/post?' + encoded_args
>>> r = http.request('POST', url)
>>> json.loads(r.data.decode('utf-8'))['args']
{'arg': 'value'}
Form data

對於PUT和POST請求(request),urllib3會自動將字典類型的field參數編碼成表格類型.

>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={'field': 'value'})
>>> json.loads(r.data.decode('utf-8'))['form']
{'field': 'value'}
JSON

在發起請求時,能夠經過定義body參數並定義headers的Content-Type參數來發送一個已通過編譯的JSON數據:

>>> import json
>>> data = {'attribute': 'value'}
>>> encoded_data = json.dumps(data).encode('utf-8')
>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     body=encoded_data,
...     headers={'Content-Type': 'application/json'})
>>> json.loads(r.data.decode('utf-8'))['json']
{'attribute': 'value'}
Files & binary data

使用multipart/form-data編碼方式上傳文件,可使用和傳入Form data數據同樣的方法進行,並將文件定義爲一個元組的形式(file_name,file_data):

>>> with open('example.txt') as fp:
...     file_data = fp.read()
>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={
...         'filefield': ('example.txt', file_data),
...     })
>>> json.loads(r.data.decode('utf-8'))['files']
{'filefield': '...'}

文件名(filename)的定義不是嚴格要求的,可是推薦使用,以使得表現得更像瀏覽器。同時,還能夠向元組中再增長一個數據來定義文件的MIME類型:

>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     fields={
...         'filefield': ('example.txt', file_data, 'text/plain'),
...     })

若是是發送原始二進制數據,只要將其定義爲body參數便可。同時,建議對headerContent-Type參數進行設置:

>>> with open('example.jpg', 'rb') as fp:
...     binary_data = fp.read()
>>> r = http.request(
...     'POST',
...     'http://httpbin.org/post',
...     body=binary_data,
...     headers={'Content-Type': 'image/jpeg'})
>>> json.loads(r.data.decode('utf-8'))['data']
b'...'

Response content

The HTTPResponse object provides status, data, and header attributes:

>>> r = http.request('GET', 'http://httpbin.org/ip')
>>> r.status
200
>>> r.data
b'{\n "origin": "104.232.115.37"\n}\n'
>>> r.headers
HTTPHeaderDict({'Content-Length': '33', ...})
JSON content

JSON content can be loaded by decoding and deserializing the data attribute of the request:

>>> import json
>>> r = http.request('GET', 'http://httpbin.org/ip')
>>> json.loads(r.data.decode('utf-8'))
{'origin': '127.0.0.1'}
Binary content

The data attribute of the response is always set to a byte string representing the response content:

>>> r = http.request('GET', 'http://httpbin.org/bytes/8')
>>> r.data
b'\xaa\xa5H?\x95\xe9\x9b\x11'

Note: For larger responses, it’s sometimes better to stream the response.

Using timeouts

使用timeout,能夠控制請求的運行時間。在一些簡單的應用中,能夠將timeout參數設置爲一個浮點數:

>>> http.request(
...     'GET', 'http://httpbin.org/delay/3', timeout=4.0)
<urllib3.response.HTTPResponse>
>>> http.request(
...     'GET', 'http://httpbin.org/delay/3', timeout=2.5)
MaxRetryError caused by ReadTimeoutError

要進行更精細的控制,可使用Timeout實例,將鏈接的timeout和讀的timeout分開設置:

>>> http.request(
...     'GET',
...     'http://httpbin.org/delay/3',
...     timeout=urllib3.Timeout(connect=1.0))
<urllib3.response.HTTPResponse>
>>> http.request(
...     'GET',
...     'http://httpbin.org/delay/3',
...     timeout=urllib3.Timeout(connect=1.0, read=2.0))
MaxRetryError caused by ReadTimeoutError

若是想讓全部的request都遵循一個timeout,能夠將timeout參數定義在PoolManager中:

>>> http = urllib3.PoolManager(timeout=3.0)
# 或者這樣
>>> http = urllib3.PoolManager(
...     timeout=urllib3.Timeout(connect=1.0, read=2.0))

當在具體的request中再次定義timeout時,會覆蓋PoolManager層面上的timeout。

請求重試(Retrying requests):

urllib3能夠自動重試冪等請求,原理和handles redirect同樣。能夠經過設置retries參數對重試進行控制。Urllib3默認進行3次請求重試,並進行3次方向改變。

給retries參數定義一個整型來改變請求重試的次數:

>>> http.requests('GET', 'http://httpbin.org/ip', retries=10)

關閉請求重試(retrying request)及重定向(redirect)只要將retries定義爲False便可:

>>> http.request(
...     'GET', 'http://nxdomain.example.com', retries=False)
NewConnectionError
>>> r = http.request(
...     'GET', 'http://httpbin.org/redirect/1', retries=False)
>>> r.status
302

關閉重定向(redirect)但保持重試(retrying request),將redirect參數定義爲False便可:

>>> r = http.request(
...     'GET', 'http://httpbin.org/redirect/1', redirect=False)
>>> r.status
302

要進行更精細的控制,可使用retry實例,經過該實例能夠對請求的重試進行更精細的控制。

例如,進行3次請求重試,可是隻進行2次重定向:

>>> http.request(
...     'GET',
...     'http://httpbin.org/redirect/3',
...     retries=urllib3.Retry(3, redirect=2))
MaxRetryError

You can also disable exceptions for too many redirects and just return the 302 response:

>>> r = http.request(
...     'GET',
...     'http://httpbin.org/redirect/3',
...     retries=urllib3.Retry(
...         redirect=2, raise_on_redirect=False))
>>> r.status
302

若是想讓全部請求都遵循一個retry策略,能夠在PoolManager中定義retry參數:

>>> http = urllib3.PoolManager(retries=False)
# 或者這樣:
>>> http = urllib3.PoolManager(
...     retries=urllib3.Retry(5, redirect=2))

當在具體的request中再次定義retry時,會覆蓋 PoolManager層面上的retry。

Errors & Exceptions

urllib3 wraps lower-level exceptions, for example:

>>> try:
...     http.request('GET', 'nx.example.com', retries=False)
>>> except urllib3.exceptions.NewConnectionError:
...     print('Connection failed.')

See exceptions for the full list of all exceptions.

Logging

If you are using the standard library logging module urllib3 will emit several logs. In some cases this can be undesirable. You can use the standard logger interface to change the log level for urllib3’s logger:

>>> logging.getLogger("urllib3").setLevel(logging.WARNING)

5、requests

requests使用的是urllib3,它繼承了urllib2的全部特性。requests有很大功能特性:

  • 支持HTTP鏈接保持和鏈接池;
  • 支持使用cookie保持會話;
  • 支持文件上傳;
  • 支持自動肯定響應內容的編碼;
  • 支持國際化的URL和POST數據自動編碼。

requests是第三方類庫,須要另外安裝。

簡單使用:
import requests
 
r = requests.get(url='http://www.baidu.com')    # 最基本的GET請求
print(r.status_code)    # 獲取返回狀態

#帶參數的GET請求,http://dict.baidu.com/s?wd=python
r = requests.get(url='http://dict.baidu.com/s', params={'wd':'python'})   
print(r.url)
print(r.text)   #打印解碼後的返回數據

關於requests更詳細的介紹,請參閱 https://mp.csdn.net/mdeditor/87564359


參考:
python中urllib, urllib2,urllib3, httplib,httplib2, request的區別 https://blog.csdn.net/permike/article/details/52437492
Python網絡請求urllib和urllib3詳解 https://www.jianshu.com/p/f05d33475c78
Python–urllib3庫詳解1 http://www.javashuo.com/article/p-tnwmtomr-cd.html
urllib2庫.官方文檔翻譯 https://blog.csdn.net/u014343243/article/details/49308043


  1. 部份內容參考Python基礎教程 ↩︎

  2. 進一步瞭解urllib2,參見中文版翻譯文檔:http://blog.csdn.net/u014343243/article/details/49308043 ↩︎

  3. urllib3官方文檔: https://urllib3.readthedocs.io/en/latest/
    urllib3其餘參考文檔: https://pypi.org/project/urllib3/ ↩︎

相關文章
相關標籤/搜索