學習一時爽,一直學習一直爽html
Hello,你們好,我是Connor,一個從無到有的技術小白。今天咱們繼續來講咱們的 Python 爬蟲,上一次咱們說到了 urllib
與 urllib3
,不知道你們看了之後有何感想,今天咱們來繼續聊聊 Python爬蟲中的另外一個經常使用庫——requests,相信你今天看了這篇文章之後必定有想要揍個人衝動。python
上一篇文章介紹了Python的網絡請求庫 urllib
和 urllib3
的使用方法,那麼,做爲一樣是網絡請求庫的 Requests
,相較於 urllib
與 urllib3
,它有哪些優點呢?git
Requests 惟一的一個非轉基因的 Python HTTP 庫,人類能夠安全享用。 警告:非專業使用其餘 HTTP 庫會致使危險的反作用,包括:安全缺陷症、冗餘代碼症、從新發明輪子症、啃文檔症、抑鬱、頭疼、甚至死亡。 ——requests官方文檔
Emmn.... 官方吐槽最爲致命,從requests的話中,你就能夠看得出它是多麼的偉大了。程序員
requests
仍是少有的被官方推薦的庫,在 urllib.request
的文檔中,有這樣的一句話來推薦 requests
:github
The Requests packageis recommended for a higher-level HTTP client interface.json
urllib
作爲Python的標準庫,由於歷史緣由,使用的方式能夠說是很是的麻煩而複雜的,並且官方文檔也十分的簡陋,經常須要去查看源碼。與之相反的是,Requests
的使用方式很是的簡單、直觀、人性化,讓程序員的精力徹底從庫的使用中解放出來。瀏覽器
吹牛皮吹了這麼久,那麼requests
庫究竟能夠強大到什麼地方呢?Twitter、Spotify、Microsoft、Amazon、Lyft、BuzzFeed、Reddit、NASA、Amazon、Google、Twilio、Mozilla、Heroku、PayPal、NPR、Obama for America、Transifex、Native Instruments、Washington Post、Twitter、SoundCloud、Kippt、Readability、以及若干不肯公開身份的聯邦政府機構都在內部使用。安全
怎麼樣,是否是有了一種想要打個人衝動了?這麼好的庫竟然不早點拿出來講,藏着掖着的...其實 requests
是很是少有的配備有官方中文文檔的第三方庫,若是有須要的話你也能夠去看看他們的官方文檔 點我走起>>>服務器
百度五分鐘解決問題,羣裏吹牛逼倆小時,哈哈哈,貌似今天你百度也要跟着吹牛兩小時了,下面咱們說點正經了,看看requests
到底應該怎麼使用吧:cookie
若是你想使用request訪問一個頁面的話,那麼你能夠直接這樣:
In [1]: import requests
In [2]: resp = requests.get('https://www.baidu.com')
In [3]: resp.status_code
Out[3]: 200
In [4]: resp.encoding
Out[4]: 'ISO-8859-1'
In [5]: resp.headers['Date']
Out[5]: 'Mon, 07 Jan 2019 07:30:15 GMT'
複製代碼
能夠看到,不管是發起請求仍是響應處理,都是很是直觀明瞭的。requests
目前能夠知足全部的請求需求,因此相較 urllib
與 urllib3
而言,你們仍是更加喜歡使用 requests
庫來發起訪問。
requests
的安裝方式與全部的第三方庫的安裝方式都是相同的,你能夠直接用 pip 進行安裝
pip install requests
複製代碼
requests
的請求再也不像urllib
同樣須要去構造各類Request、opener和handler,使用requests
構造的方法,並在其中傳入須要的參數便可。
在 reqeuest
模塊中,每一種method方法都有對應的封裝好的函數供你使用,好比說,進行GET請求的時候,你能夠直接使用 get()
方法:
In [1]: import requests
In [2]: resp = requests.get('https://www.baidu.com')
複製代碼
而當你須要進行POST請求的時候,你能夠直接使用封裝好了的 post()
方法來進行訪問:
In [3]: resp = requests.post('https://www.baidu.com',
data = {'hello': 'world'})
複製代碼
其它的請求方式也都有相對應的請求方法來進行請求,以下:
In [4]: resp = requests.put('http://httpbin.org/put', data = {'key':'value'})
In [5]: resp = requests.delete('http://httpbin.org/delete')
In [6]: resp = requests.head('http://httpbin.org/get')
In [7]: resp = requests.options('http://httpbin.org/get')
複製代碼
雖然上述的幾種方法並不經常使用,可是 requests
官方依舊很人性化的將它們都封裝了進去。
傳遞URL參數的時候不再用使用 urllib
中的方法來將URL拼接起來了,它和 urllib3
的方式一致,直接將要拼接的 URL 構形成字典,傳遞給 params參數便可,和 urllib3
中的 request
方法中的 field
屬性一致:
In [1]: import requests
In [2]: params = {'searchtype': '1', 'bookname': 'Detroit'}
In [3]: resp = requests.get('https://httpbin.org/get', params=params)
In [4]: resp.url
Out[4]: 'https://httpbin.org/get?searchtype=1&bookname=Detroit'
複製代碼
能夠清晰的看到,request
自動幫咱們把 params
參數拼接到了一塊兒。固然,有的時候咱們也會遇到同名不一樣值的參數,可是python語法中並不支持鍵名的重複,這個時候咱們能夠把屬性名相同的參數變成一個列表,request會自動的幫咱們把它們拼接到一塊兒:
In [1]: import requests
In [2]: params = {'name': 'Connor', 'others': ['abc', 'def']}
In [3]: resp = requests.get('https://www.httpbin.org/get', params=params)
In [4]: resp.url
Out[4]: 'https://www.httpbin.org/get?name=Connor&others=abc&others=def'
複製代碼
毫無疑問,requests
也可以設置 headers
參數,這是章口就萊的事,下面咱們來看看如何設置 headers
:
import requests
datas = {'name': 'Connor', 'age': '22', 'height': '166'}
headers = {'User-Agent': 'ABCDE'}
resp = requests.post('https://www.httpbin.org/post', headers=headers, data=datas)
print(resp.json()['headers'])
複製代碼
運行以後的結果以下:
{'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate', 'Connection': 'close', 'Content-Length': '29', 'Content-Type': 'application/x-www-form-urlencoded', 'Host': 'www.httpbin.org', 'User-Agent': 'ABCDE'}
複製代碼
能夠明顯的看到,咱們的 User-Agent
屬性已經變成了以前設定的 ABCDE,仍是很是簡單的
reqeusts
還能夠幫咱們構建cookie,咱們不用再建立CookieJar對象了,直接將你的 Cookie傳遞給Cookies參數便可:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/cookies'
In [3]: cook = {'leijun': 'Are you OK?'}
In [4]: resp = requests.get(url, cookies=cook)
In [5]: resp.text
Out[5]: '{\n "cookies": {\n "leijun": "Are you OK?"\n }\n}\n'
複製代碼
requests
連cookie都幫咱們構建了,固然也少不了代理的構建,當咱們須要使用代理的時候須要把構造的字典傳遞給 proxies
參數便可
import requests
url = 'https://www.httpbin.org/ip'
datas = {'name': 'Connor', 'age': '22', 'height': '166'}
headers = {'User-Agent': 'ABCDE'}
proxy = {'http': 'http://110.52.235.90:9999', 'https': 'https://110.52.235.90:9999'}
resp1 = requests.get(url)
resp2 = requests.get(url, proxies=proxy)
print(resp1.text, resp2.text)
複製代碼
運行以後的結果以下:
{"origin": "221.192.178.130"}
{"origin": "110.52.235.90"}
複製代碼
再網絡請求中,咱們經常會遇到狀態碼是3開頭的重定向問題,在 requests
中默認是開啓重定向的,即當咱們遇到重定向的時候,reqeusts
會自動幫咱們繼續訪問,你也能夠手動關閉重定向:
In [1]: import requests
In [2]: url = 'http://www.jianshu.com'
In [3]: resp = requests.get(url, allow_redirects=False)
In [4]: resp.status_code
Out[4]: 301
複製代碼
有些時候,當咱們使用了抓包工具的時候,因爲抓包工具提供的證書不是受信任的數字證書頒發機構頒發的,因此會致使證書驗證失敗,這時咱們應該關閉證書驗證。
在請求的時候,咱們能夠關閉證書驗證,只須要將 verify
屬性設置爲 False
便可:
In [1]: import requests
In [2]: resp = requests.get('https://www.baidu.com', verify=False)
d:\software\python\python\lib\site-packages\urllib3\connectionpool.py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
複製代碼
這個時候你會發現,關閉驗證後會有一個煩人的847警告,你可使用如下方式來關閉警告:
from requests.packages.urllib3.exceptions import InsecureRequestWarning
# 禁用安全請求警告
requests.packages.urllib3.disable_warnings(InsecureRequestWarning)
複製代碼
當咱們訪問一個網站的時候,若是訪問時間過久,或者響應時間太長,可能對咱們的效率有很大的影響,這個時候咱們能夠設置超時時間,放棄一些數據來提高爬蟲的效率。你只須要爲其設置timeout
參數便可:
In [1]: import requests
In [2]: requests.get('http://github.com', timeout=0.001)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
requests.exceptions.Timeout: HTTPConnectionPool(host='github.com', port=80): Request timed out. (timeout=0.001)
複製代碼
經過 requests
發起請求獲得的對象是 Resopnse
對象,經過這個對象咱們能夠方便的獲取響應的內容。
在上一式咱們講述 urllib
與 urllib3
的時候,咱們獲取到的內容是二進制格式的,這個時候須要咱們本身手動的 decode()
將二進制的bytes數據轉換成咱們能夠讀懂的字符串數據。可是在 requests
中,它的 text
屬性會主動的經過可能的方式幫咱們解碼:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/get'
In [3]: resp = requests.get(url)
In [4]: resp.text
Out[4]: '{\n "args": {}, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip, deflate", \n "Connection": "close", \n "Host": "www.httpbin.org", \n "User-Agent": "python-requests/2.21.0"\n }, \n "origin": "221.192.178.130", \n "url": "https://www.httpbin.org/get"\n}\n'
複製代碼
requests
會主動的幫咱們進行解碼,它會經過響應的報頭來猜想網頁的編碼是什麼,而後根據猜想的編碼來解碼網頁的內容。大部分的網頁他都可以正確的解碼,但也有解碼不正確的時候,若是發現解碼不正確了,咱們就須要本身來手動的指定解碼的編碼格式:
import requests
url = 'http://www.quanshuwang.com/'
resp = requests.get(url)
resp.encoding = 'GBK'
print(resp.text)
複製代碼
在這裏我給你們推薦一個其餘的python自帶的庫,這個庫也是在猜想網頁的編碼格式,可是這個庫的準確率更高一些吧。何況咱們每次指定解碼格式就要求咱們去看網頁的編碼格式。像新浪微博這樣的網站,它在無序可視化的頁面上使用的是 GBK 編碼格式,在須要可視的頁面上的編碼格式是 UTF-8,咱們不但願每次訪問都手動的去更改它的編碼格式,這個時候就用下面這種方法:
這個時候,咱們可使用 chardet
中的 detect
方法:
import requests
import chardet
url = 'https://www.httpbin.org/get'
resp = requests.get(url)
resp.encoding = chardet.detect(resp.content)
print(resp.text)
複製代碼
若是你須要得到網頁的原始二進制數據的時候,那麼使用 content
屬性便可:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/get'
In [3]: resp = requests.get(url)
In [4]: resp.content
Out[4]: b'{\n "args": {}, \n "headers": {\n "Accept": "*/*", \n "Accept-Encoding": "gzip, deflate", \n "Connection": "close", \n "Host": "www.httpbin.org", \n "User-Agent": "python-requests/2.21.0"\n }, \n "origin": "221.192.178.130", \n "url": "https://www.httpbin.org/get"\n}\n'
複製代碼
若是咱們訪問以後得到的數據是JSON格式的,那麼咱們可使用json()
方法,直接獲取轉換成字典格式的數據:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/get'
In [3]: resp = requests.get(url)
In [4]: resp.json()
Out[4]:
{'args': {},
'headers': {'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate',
'Connection': 'close',
'Host': 'www.httpbin.org',
'User-Agent': 'python-requests/2.21.0'},
'origin': '221.192.178.130',
'url': 'https://www.httpbin.org/get'}
複製代碼
有時候咱們過於頻繁的訪問一個網址以後,或者某些網站對訪問速度有限制的話,那咱們應該判斷如下響應的狀態碼,而後再判斷是否須要數據的提取。你能夠經過 status_code
屬性來獲取響應的狀態碼:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/get'
In [3]: resp = requests.get(url)
In [4]: resp.status_code
Out[4]: 200
複製代碼
當咱們進行了訪問以後,若是你想查看該網頁的響應報頭,那麼你能夠經過 headers
屬性來查看你的響應報頭:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/get'
In [3]: resp = requests.get(url)
In [4]: resp.headers
Out[4]: {'Connection': 'keep-alive', 'Server': 'gunicorn/19.9.0', 'Date': 'Mon, 07 Jan 2019 11:36:04 GMT', 'Content-Type': 'application/json', 'Content-Length': '277', 'Access-Control-Allow-Origin': '*', 'Access-Control-Allow-Credentials': 'true', 'Via': '1.1 vegur'}
複製代碼
你能夠經過響應對象的 cookies
屬性來獲取服務器返回的 cookies
:
In [1]: import requests
In [2]: url = 'https://www.httpbin.org/get'
In [3]: resp = requests.get(url)
In [4]: resp.cookies
Out[4]: <RequestsCookieJar[]>
複製代碼
返回的cookies是一個CookieJar對象,若是你想使用這個cookie,你仍是須要構建CookieJar對象。cookies
在後續的內容裏我會專門抽出一節課來說這個的,這裏咱們掠過,只須要知道經過 cookie
屬性能夠獲取從網頁上訪問的 cookies
便可。
你也能夠經過 url
屬性來查看響應的url,你能夠經過這種方式來判斷網頁是否進行了重定向等各種操做:
In [1]: import requests
In [2]: url = 'http://www.jianshu.com'
In [3]: resp = requests.get(url)
In [4]: resp.url
Out[4]: 'https://www.jianshu.com'
複製代碼
在 requests
中,實現了 Session
會話功能,當咱們使用 Session
的時候,可以像瀏覽器同樣,在沒有關閉瀏覽器的時候,保持訪問的狀態,這個功能經常用於登錄以後,能夠避免咱們一次又一次的傳遞 cookies。session
其實很是的簡單易用,它和 requests
對象幾乎沒有任何的差異,requests
的經常使用方法在 session
這裏依舊適用。下面咱們舉一個簡單的例子:
import requests
url = 'https://www.httpbin.org/cookies'
session = requests.session()
resp = sesssion.get('https://www.httpbin.org/get')
print(resp.text)
複製代碼
運行結果以下:
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Cookie": "eare=https://www.httpbin.org", "Host": "www.httpbin.org", "User-Agent": "python-requests/2.20.0"}, "origin": "221.192.178.173", "url": "https://www.httpbin.org/get"}
複製代碼
從上面的運行結果中咱們能夠看到,session
操做起來仍是很是容易上手的,它的方法和requests
的用法幾乎是徹底一致的。固然 session
也有本身更爲獨有的功能,下面咱們一塊兒來看看它還有哪些其它的功能:
既然以前咱們說 session
是一個能夠大大提升效率的工具,能夠保持一些數據,不用頻繁的重複傳參,那咱們來試試看:
import requests
url = 'https://www.httpbin.org/cookies'
session = requests.session()
cook = {'eare': 'https://www.httpbin.org'}
resp = session.get(url, cookies=cook)
print(resp.text)
resp = session.get('https://www.httpbin.org/get')
print(resp.text)
複製代碼
運行後的結果以下:
{"cookies": {"eare": "https://www.httpbin.org"}}
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Host": "www.httpbin.org", "User-Agent": "python-requests/2.20.0"}, "origin": "221.192.178.173", "url":"https://www.httpbin.org/get"}
複製代碼
經過上面的結果咱們會發現,第二次訪問的時候並無維持第一次訪問時設置的 session
啊,這是爲何呢?難道是session的 doman
有問題?不是的,經過單次訪問傳參的方式來添加參數是不會對下一次訪問起做用的,這個時候咱們須要使用一個方法 session.args.updata()
:
import requests
url = 'https://www.httpbin.org/cookies'
session = requests.session()
cook = {'eare': 'https://www.httpbin.org'}
session.cookies.update(cook)
resp = session.get(url)
print(resp.text)
resp = session.get('https://www.httpbin.org/get')
print(resp.text)
複製代碼
此次咱們再來看運行結果:
{"cookies": {"eare": "https://www.httpbin.org"}}
{"args": {}, "headers": {"Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Cookie": "eare=https://www.httpbin.org", "Host": "www.httpbin.org", "User-Agent": "python-requests/2.20.0"}, "origin": "221.192.178.173", "url": "https://www.httpbin.org/get"}
複製代碼
這一次咱們明顯的發現了第二次訪問的時候帶上了第一次設置的 cookie
參數,這樣設置的話咱們以後的每次訪問都無需再次傳參了。固然,前提是在同一個域名下的訪問。關於 cookie
的做用域的問題,我在以前的文章:Python 爬蟲十六式 - 第一式:HTTP協議 >>> 中已經寫到過了,若是看不懂的話請參照該文章。
在上面的內容中,有一點尤其須要注意: session.args.updata()
並不指實際的方法,這只是一類參數的統稱,我的的命名習慣,若有錯誤,歡迎指出! session.args.updata()
包括以下的幾種參數:
名稱 | 做用 |
---|---|
headers | 設置session的請求頭參數 |
cookies | 設置session的cookies |
params | 設置session的url拼接參數 |
proxies | 設置session的proxy代理 |
session
固然也爲咱們提供了批量管理驗證的方法,這與 requests
中的管理方式幾乎相同,但和 session
的其它參數的管理相比又有所不一樣。session.verify 是一個屬性,它是一個 Boolean
型的變量,你只須要將它設置爲 False
便可關閉 session
對象的全部證書驗證:
import requests
url = 'https://www.httpbin.org/user-agent'
session = requests.session()
head = {'User-Agent': 'ABCDE'}
session.verify = False
session.headers.update(head)
resp = session.get(url)
print(resp.text)
複製代碼
運行結果以下:
py:847: InsecureRequestWarning: Unverified HTTPS request is being made. Adding certificate verification is strongly advised. See: https://urllib3.readthedocs.io/en/latest/advanced-usage.html#ssl-warnings
InsecureRequestWarning)
{"user-agent": "ABCDE"}
複製代碼
嗯,又看到了煩人的 847報錯,想要關閉它的話查看本文第2.3.7節證書驗證,裏面有如何關閉證書驗證警告的方法,點我直達 >>>
好啦,到這裏咱們就說完 requests
的使用了,不知道你學到了多少東西,可是依舊但願這些東西對你有幫助,最後仍是那句話送給你們:
學習一時爽, 一直學習一直爽!
我是一個從無到有的技術小白,Connor,咱們下期再見!
Python 爬蟲十六式 - 第一式:HTTP協議 >>>
Python 爬蟲十六式 - 第二式:urllib 與 urllib3 >>>
Python 爬蟲十六式 - 第四式:使用Xpath提取網頁內容 >>>
Python 爬蟲十六式 - 第五式:BeautifulSoup,美味的湯 >>>
Python 爬蟲十六式 - 第六式:JQuery的假兄弟-pyquery >>>
Python 爬蟲十六式 - 第七式:正則的藝術 >>>
Python 爬蟲十六式 - 第八式:實例解析-全書網 >>>