python的網路請求
原文連結:https://www.jianshu.com/p/f05d33475c78
urllib
是Python中請求url連線的官方標準庫,在Python2中主要為urllib和urllib2,在Python3中整合成了urllib。
而urllib3則是增加了連線池等功能,兩者互相都有補充的部分。
urllib
urllib作為Python的標準庫,基本上涵蓋了基礎的網路請求功能。
urllib.request
urllib中,request
這個模組主要負責構造和發起網路請求,並在其中加入Headers、Proxy等。
發起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()
一下,轉換成字串格式。
發起POST請求
urlopen()
urlopen()
方法中傳入data引數時,則會發起POST請求。
注意:傳遞的data資料需要為bytes格式。
設定timeout引數還可以設定超時時間,如果請求時間超出,那麼就會丟擲異常。
from urllib import request
resp = request.urlopen('http://httpbin.org', data=b'word=hello', timeout=10)
print(resp.read().decode())
新增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())
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。
新增Cookie
為了在請求時能帶上Cookie資訊,我們需要重新構造一個opener。
使用request.build_opener方法來進行構造opener,將我們想要傳遞的cookie配置到opener中,然後使用這個opener的open方法來發起請求。
from http import cookiejar
from urllib import request
url = 'http://httpbin.org/cookies'
# 建立一個cookiejar物件
cookie = cookiejar.CookieJar()
# 使用HTTPCookieProcessor建立cookie處理器
cookies = request.HTTPCookieProcessor(cookie)
# 並以它為引數建立Opener物件
opener = request.build_opener(cookies)
# 使用這個opener來發起請求
resp = opener.open(url)
print(resp.read().decode())
或者也可以把這個生成的opener使用install_opener方法來設定為全域性的。
則之後使用urlopen方法發起請求時,都會帶上這個cookie。
# 將這個opener設定為全域性的opener
request.install_opener(opener)
resp = request.urlopen(url)
設定Proxy代理
使用爬蟲來爬取資料的時候,常常需要使用代理來隱藏我們的真實IP。
from urllib import request
url = 'http://httpbin.org/ip'
proxy = {'http':'50.233.137.33:80','https':'50.233.137.33:80'}
# 建立代理處理器
proxies = request.ProxyHandler(proxy)
# 建立opener物件
opener = request.build_opener(proxies)
resp = opener.open(url)
print(resp.read().decode())
下載資料到本地
在我們進行網路請求時常常需要儲存圖片或音訊等資料到本地,一種方法是使用python的檔案操作,將read()獲取的資料儲存到檔案中。
而urllib
提供了一個urlretrieve()
方法,可以簡單的直接將請求獲取的資料儲存成檔案。
from urllib import request
url = 'http://python.org/'
request.urlretrieve(url, 'python.html')
urlretrieve()
方法傳入的第二個引數為檔案儲存的位置,以及檔名。
注:urlretrieve()
方法是python2直接移植過來的方法,以後有可能在某個版本中棄用。
urllib.response
在使用urlopen()
方法或者opener的open()
方法發起請求後,獲得的結果是一個response
物件。
這個物件有一些方法和屬性,可以讓我們對請求返回的結果進行一些處理。
-
read()
獲取響應返回的資料,只能使用一次。
-
getcode()
獲取伺服器返回的狀態碼。
-
getheaders()
獲取返回響應的響應報頭。
-
geturl()
獲取訪問的url。
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%8D%97%E5%8C%97'
如果需要將編碼後的資料轉換回來,可以使用unquote()
方法。
>>> parse.unquote('%E5%8D%97%E5%8C%97')
'南北'
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'
urllib.error
在urllib
中主要設定了兩個異常,一個是URLError
,一個是HTTPError
,HTTPError
是URLError
的子類。
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
urllib3
Urllib3是一個功能強大,條理清晰,用於HTTP客戶端的Python庫。許多Python的原生系統已經開始使用urllib3。Urllib3提供了很多python標準庫urllib裡所沒有的重要特性:
- 執行緒安全
- 連線池
- 客戶端SSL/TLS驗證
- 檔案分部編碼上傳
- 協助處理重複請求和HTTP重定位
- 支援壓縮編碼
- 支援HTTP和SOCKS代理
安裝
urllib3是一個第三方庫,安裝非常簡單,pip安裝即可:
pip install urllib3
使用
urllib3
主要使用連線池進行網路請求的訪問,所以訪問之前我們需要建立一個連線池物件,如下所示:
>>> import urllib3
>>> http = urllib3.PoolManager()
>>> r = http.request('GET', 'http://httpbin.org/robots.txt')
>>> r.status
200
>>> r.data
'User-agent: *\nDisallow: /deny\n'
設定headers
headers={'X-Something': 'value'}
resp = http.request('GET', 'http://httpbin.org/headers', headers=headers)
設定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)
設定代理
>>> 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中