以前咱們用了 urllib 庫,這個做爲入門的工具仍是不錯的,對了解一些爬蟲的基本理念,掌握爬蟲爬取的流程有所幫助。入門以後,咱們就須要學習一些更加高級的內容和工具來方便咱們的爬取。那麼這一節來簡單介紹一下 requests 庫的基本用法。html
注:Python 版本依然基於 2.7python
如下內容大多來自於官方文檔,本文進行了一些修改和總結。要了解更多能夠參考git
官方文檔github
利用 pip 安裝web
1
|
$ pip install requests
|
或者利用 easy_installjson
1
|
$ easy_install requests
|
經過以上兩種方法都可以完成安裝。api
首先咱們引入一個小例子來感覺一下瀏覽器
1
2
3
4
5
6
7
8
|
import requests
r = requests.get('http://cuiqingcai.com')
print type(r)
print r.status_code
print r.encoding
#print r.text
print r.cookies
|
以上代碼咱們請求了本站點的網址,而後打印出了返回結果的類型,狀態碼,編碼方式,Cookies等內容。服務器
運行結果以下cookie
1
2
3
4
|
<class 'requests.models.Response'>
200
UTF-8
<RequestsCookieJar[]>
|
怎樣,是否是很方便。別急,更方便的在後面呢。
requests庫提供了http全部的基本請求方式。例如
1
2
3
4
5
|
r = requests.post("http://httpbin.org/post")
r = requests.put("http://httpbin.org/put")
r = requests.delete("http://httpbin.org/delete")
r = requests.head("http://httpbin.org/get")
r = requests.options("http://httpbin.org/get")
|
嗯,一句話搞定。
最基本的GET請求能夠直接用get方法
1
|
r = requests.get("http://httpbin.org/get")
|
若是想要加參數,能夠利用 params 參數
1
2
3
4
5
|
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.get("http://httpbin.org/get", params=payload)
print r.url
|
運行結果
1
|
http://httpbin.org/get?key2=value2&key1=value1
|
若是想請求JSON文件,能夠利用 json() 方法解析
例如本身寫一個JSON文件命名爲a.json,內容以下
1
2
3
|
["foo", "bar", {
"foo": "bar"
}]
|
利用以下程序請求並解析
1
2
3
4
5
|
import requests
r = requests.get("a.json")
print r.text
print r.json()
|
運行結果以下,其中一個是直接輸出內容,另一個方法是利用 json() 方法解析,感覺下它們的不一樣
1
2
3
4
|
["foo", "bar", {
"foo": "bar"
}]
[u'foo', u'bar', {u'foo': u'bar'}]
|
若是想獲取來自服務器的原始套接字響應,能夠取得 r.raw 。 不過須要在初始請求中設置 stream=True 。
1
2
3
4
5
|
r = requests.get('https://github.com/timeline.json', stream=True)
r.raw
<requests.packages.urllib3.response.HTTPResponse object at 0x101194810>
r.raw.read(10)
'\x1f\x8b\x08\x00\x00\x00\x00\x00\x00\x03'
|
這樣就獲取了網頁原始套接字內容。
若是想添加 headers,能夠傳 headers 參數
1
2
3
4
5
6
|
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
headers = {'content-type': 'application/json'}
r = requests.get("http://httpbin.org/get", params=payload, headers=headers)
print r.url
|
經過headers參數能夠增長請求頭中的headers信息
對於 POST 請求來講,咱們通常須要爲它增長一些參數。那麼最基本的傳參方法能夠利用 data 這個參數。
1
2
3
4
5
|
import requests
payload = {'key1': 'value1', 'key2': 'value2'}
r = requests.post("http://httpbin.org/post", data=payload)
print r.text
|
運行結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
|
{
"args": {},
"data": "",
"files": {},
"form": {
"key1": "value1",
"key2": "value2"
},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "23",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
},
"json": null,
"url": "http://httpbin.org/post"
}
|
能夠看到參數傳成功了,而後服務器返回了咱們傳的數據。
有時候咱們須要傳送的信息不是表單形式的,須要咱們傳JSON格式的數據過去,因此咱們能夠用 json.dumps() 方法把表單數據序列化。
1
2
3
4
5
6
7
|
import json
import requests
url = 'http://httpbin.org/post'
payload = {'some': 'data'}
r = requests.post(url, data=json.dumps(payload))
print r.text
|
運行結果
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
{
"args": {},
"data": "{\"some\": \"data\"}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "16",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
},
"json": {
"some": "data"
},
"url": "http://httpbin.org/post"
}
|
經過上述方法,咱們能夠POST JSON格式的數據
若是想要上傳文件,那麼直接用 file 參數便可
新建一個 a.txt 的文件,內容寫上 Hello World!
1
2
3
4
5
6
|
import requests
url = 'http://httpbin.org/post'
files = {'file': open('test.txt', 'rb')}
r = requests.post(url, files=files)
print r.text
|
能夠看到運行結果以下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
{
"args": {},
"data": "",
"files": {
"file": "Hello World!"
},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Content-Length": "156",
"Content-Type": "multipart/form-data; boundary=7d8eb5ff99a04c11bb3e862ce78d7000",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
},
"json": null,
"url": "http://httpbin.org/post"
}
|
這樣咱們便成功完成了一個文件的上傳。
requests 是支持流式上傳的,這容許你發送大的數據流或文件而無需先把它們讀入內存。要使用流式上傳,僅需爲你的請求體提供一個類文件對象便可
1
2
|
with open('massive-body') as f:
requests.post('http://some.url/streamed', data=f)
|
這是一個很是實用方便的功能。
若是一個響應中包含了cookie,那麼咱們能夠利用 cookies 變量來拿到
1
2
3
4
5
6
|
import requests
url = 'http://example.com'
r = requests.get(url)
print r.cookies
print r.cookies['example_cookie_name']
|
以上程序僅是樣例,能夠用 cookies 變量來獲得站點的 cookies
另外能夠利用 cookies 變量來向服務器發送 cookies 信息
1
2
3
4
5
6
|
import requests
url = 'http://httpbin.org/cookies'
cookies = dict(cookies_are='working')
r = requests.get(url, cookies=cookies)
print r.text
|
運行結果
1
|
'{"cookies": {"cookies_are": "working"}}'
|
能夠已經成功向服務器發送了 cookies
能夠利用 timeout 變量來配置最大請求時間
1
|
requests.get('http://github.com', timeout=0.001)
|
注:timeout 僅對鏈接過程有效,與響應體的下載無關。
也就是說,這個時間只限制請求的時間。即便返回的 response 包含很大內容,下載須要必定時間,然而這並無什麼卵用。
在以上的請求中,每次請求其實都至關於發起了一個新的請求。也就是至關於咱們每一個請求都用了不一樣的瀏覽器單獨打開的效果。也就是它並非指的一個會話,即便請求的是同一個網址。好比
1
2
3
4
5
|
import requests
requests.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = requests.get("http://httpbin.org/cookies")
print(r.text)
|
結果是
1
2
3
|
{
"cookies": {}
}
|
很明顯,這不在一個會話中,沒法獲取 cookies,那麼在一些站點中,咱們須要保持一個持久的會話怎麼辦呢?就像用一個瀏覽器逛淘寶同樣,在不一樣的選項卡之間跳轉,這樣其實就是創建了一個長久會話。
解決方案以下
1
2
3
4
5
6
|
import requests
s = requests.Session()
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
r = s.get("http://httpbin.org/cookies")
print(r.text)
|
在這裏咱們請求了兩次,一次是設置 cookies,一次是得到 cookies
運行結果
1
2
3
4
5
|
{
"cookies": {
"sessioncookie": "123456789"
}
}
|
發現能夠成功獲取到 cookies 了,這就是創建一個會話到做用。體會一下。
那麼既然會話是一個全局的變量,那麼咱們確定能夠用來全局的配置了。
1
2
3
4
5
6
|
import requests
s = requests.Session()
s.headers.update({'x-test': 'true'})
r = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
print r.text
|
經過 s.headers.update 方法設置了 headers 的變量。而後咱們又在請求中設置了一個 headers,那麼會出現什麼結果?
很簡單,兩個變量都傳送過去了。
運行結果
1
2
3
4
5
6
7
8
9
10
|
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1",
"X-Test": "true",
"X-Test2": "true"
}
}
|
若是get方法傳的headers 一樣也是 x-test 呢?
1
|
r = s.get('http://httpbin.org/headers', headers={'x-test': 'true'})
|
嗯,它會覆蓋掉全局的配置
1
2
3
4
5
6
7
8
9
|
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1",
"X-Test": "true"
}
}
|
那若是不想要全局配置中的一個變量了呢?很簡單,設置爲 None 便可
1
|
r = s.get('http://httpbin.org/headers', headers={'x-test': None})
|
運行結果
1
2
3
4
5
6
7
8
|
{
"headers": {
"Accept": "*/*",
"Accept-Encoding": "gzip, deflate",
"Host": "httpbin.org",
"User-Agent": "python-requests/2.9.1"
}
}
|
嗯,以上就是 session 會話的基本用法
如今隨處可見 https 開頭的網站,Requests能夠爲HTTPS請求驗證SSL證書,就像web瀏覽器同樣。要想檢查某個主機的SSL證書,你可使用 verify 參數
如今 12306 證書不是無效的嘛,來測試一下
1
2
3
4
|
import requests
r = requests.get('https://kyfw.12306.cn/otn/', verify=True)
print r.text
|
結果
1
|
requests.exceptions.SSLError: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:590)
|
果然如此
來試下 github 的
1
2
3
4
|
import requests
r = requests.get('https://github.com', verify=True)
print r.text
|
嗯,正常請求,內容我就不輸出了。
若是咱們想跳過剛纔 12306 的證書驗證,把 verify 設置爲 False 便可
1
2
3
4
|
import requests
r = requests.get('https://kyfw.12306.cn/otn/', verify=False)
print r.text
|
發現就能夠正常請求了。在默認狀況下 verify 是 True,因此若是須要的話,須要手動設置下這個變量。
若是須要使用代理,你能夠經過爲任意請求方法提供 proxies 參數來配置單個請求
1
2
3
4
5
6
7
|
import requests
proxies = {
"https": "http://41.118.132.69:4433"
}
r = requests.post("http://httpbin.org/post", proxies=proxies)
print r.text
|
也能夠經過環境變量 HTTP_PROXY 和 HTTPS_PROXY 來配置代理
1
2
|
export HTTP_PROXY="http://10.10.1.10:3128"
export HTTPS_PROXY="http://10.10.1.10:1080"
|
經過以上方式,能夠方便地設置代理。
以上講解了 requests 中最經常使用的參數,若是須要用到更多,請參考官方文檔 API
以上總結了一下 requests 的基本用法,若是你對爬蟲有了必定的基礎,那麼確定能夠很快上手,在此就很少贅述了。
練習纔是王道,你們儘快投注於實踐中吧。