人生苦短,我用 Python
前文傳送門:
小白學(xué) Python 爬蟲(chóng)(1):開(kāi)篇
小白學(xué) Python 爬蟲(chóng)(2):前置準(zhǔn)備(一)基本類庫(kù)的安裝
小白學(xué) Python 爬蟲(chóng)(3):前置準(zhǔn)備(二)Linux基礎(chǔ)入門
小白學(xué) Python 爬蟲(chóng)(4):前置準(zhǔn)備(三)Docker基礎(chǔ)入門
小白學(xué) Python 爬蟲(chóng)(5):前置準(zhǔn)備(四)數(shù)據(jù)庫(kù)基礎(chǔ)
小白學(xué) Python 爬蟲(chóng)(6):前置準(zhǔn)備(五)爬蟲(chóng)框架的安裝
小白學(xué) Python 爬蟲(chóng)(7):HTTP 基礎(chǔ)
小白學(xué) Python 爬蟲(chóng)(8):網(wǎng)頁(yè)基礎(chǔ)
小白學(xué) Python 爬蟲(chóng)(9):爬蟲(chóng)基礎(chǔ)
小白學(xué) Python 爬蟲(chóng)(10):Session 和 Cookies
引言
看到本篇實(shí)戰(zhàn)的同學(xué)有沒(méi)有很激動(dòng),經(jīng)過(guò)了前面十篇基礎(chǔ)內(nèi)容的折磨,終于等到實(shí)戰(zhàn)章節(jié)了,有沒(méi)有一種激動(dòng)之情。
想到一句歌詞:終于等到你~~~
首先,官方文檔地址敬上:
官方文檔地址:https://docs./3/library/urllib.html
在前面的前置準(zhǔn)備中,我們一起安裝了很多第三方的請(qǐng)求類庫(kù),在介紹這些第三方的類庫(kù)前,我們先介紹一下 Python3 本身自帶的一個(gè) HTTP 請(qǐng)求庫(kù) urllib 。
urllib
urllib 是一個(gè)軟件包,它包含了幾個(gè)用于處理 URL 的模塊:
- request: 基礎(chǔ)的 HTTP 請(qǐng)求模塊。
- error: 異常處理模塊。
- parse: 用于解析 URL 的模塊。
- robotparser: 識(shí)別網(wǎng)站中 robots.txt 文件。
urllib.request
如果要說(shuō)怎么學(xué)習(xí)最快,當(dāng)然是查看官方文檔,首先祭出官方文檔的地址。
urllib.request官方文檔: https://docs./3/library/urllib.request.html#module-urllib.request
這里的解釋是最權(quán)威了,并且目前已經(jīng)提供了中文版本,不過(guò)那個(gè)翻譯看起來(lái)像是機(jī)器翻譯的,質(zhì)量并不高。
如果實(shí)在看不懂,就只能看小編 XBB 了。
urlopen
urllib.request 模塊提供了最基本的構(gòu)造 HTTP 請(qǐng)求的方法,使用它可以模擬瀏覽器的一個(gè)請(qǐng)求發(fā)起過(guò)程,同時(shí)它還帶有處理授權(quán)驗(yàn)證(authenticaton)、重定向(redirection)、瀏覽器Cookies以及其他內(nèi)容。
語(yǔ)法:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
這么厲害的模塊當(dāng)然是要趕緊嘗試一下,首先我們使用它爬取一下小編的博客站:
import urllib.request
response = urllib.request.urlopen('https://www./')
print(response.read().decode('utf-8'))
運(yùn)行結(jié)果小編這里就不展示,比較長(zhǎng)。
短短的三行代碼,我們就完成了網(wǎng)站源代碼的抓取,是不是很簡(jiǎn)單。
當(dāng)我們得到源代碼之后,想要的鏈接、文本信息,都可以從中提取出來(lái)。
各位同學(xué)看到打印的內(nèi)容,可以猜測(cè)一下這個(gè)內(nèi)容是什么數(shù)據(jù)類型,會(huì)是字符串類型么?
使用 type() 看一下就知道了。
print(type(response))
結(jié)果:
<class 'http.client.HTTPResponse'>
urlopen 返回了一個(gè) HTTPResponse 類型的對(duì)象。
官方文檔對(duì) HTTPResponse 的解釋如下:
An HTTPResponse instance wraps the HTTP response from the server. It provides access to the request headers and the entity body. The response is an iterable object and can be used in a with statement.
大意是說(shuō) HTTPResponse 是對(duì) HTTP 響應(yīng)的包裝。它提供了對(duì)請(qǐng)求頭和請(qǐng)求體的訪問(wèn)。這個(gè)響應(yīng)是一個(gè)可以迭代的對(duì)象。
HTTPResponse 主要包含 read() 、 readline() 、 getheader(name) 、 getheaders() 、 fileno() 等方法,以及 msg 、 version 、 status 、 reason 、 debuglevel 、 closed 等屬性。
import urllib.request
# 獲取HTTP協(xié)議版本號(hào)(10 for HTTP/1.0, 11 for HTTP/1.1)
print(response.version)
# 獲取響應(yīng)碼
print(response.status)
print(response.getcode())
# 獲取響應(yīng)描述字符串
print(response.reason)
# 獲取實(shí)際請(qǐng)求的頁(yè)面url(防止重定向用)
print(response.geturl())
# 獲取特定響應(yīng)頭信息
print(response.getheader(name="Content-Type"))
# 獲取響應(yīng)頭信息,返回二元元組列表
print(response.getheaders())
# 獲取響應(yīng)頭信息,返回字符串
print(response.info())
# 讀取響應(yīng)體
print(response.readline().decode('utf-8'))
結(jié)果有點(diǎn)長(zhǎng),小編就不貼了,各位同學(xué)可以自己運(yùn)行一下。
data
data 用來(lái)指明發(fā)往服務(wù)器請(qǐng)求中的額外的參數(shù)信息, data 默認(rèn)是 None ,此時(shí)以 GET 方式發(fā)送請(qǐng)求;當(dāng)用戶給出 data 參數(shù)的時(shí)候,改為 POST 方式發(fā)送請(qǐng)求。
來(lái)個(gè)示例吧,這里我們使用 httpbin 提供的測(cè)試接口,此項(xiàng)目為 postmanlabs 提供在 Github開(kāi)源的項(xiàng)目, Github 地址為:https://github.com/postmanlabs/httpbin 。
import urllib.request
import urllib.parse
post_data = bytes(urllib.parse.urlencode({'name': 'geekdigging', 'hello':'world'}), encoding='utf8')
response = urllib.request.urlopen('https:///post', data = post_data)
print(response.read().decode('utf-8'))
值得注意的是,這里我們傳遞了兩個(gè)參數(shù),是以 dict 的方式傳遞的,它一定需要被轉(zhuǎn)碼成 bytes 字節(jié)流, 這里使用了 bytes() 方法,第一個(gè)參數(shù)是我們需要轉(zhuǎn)換的字符串,第二個(gè)參數(shù)是編碼方式。
這里我們請(qǐng)求的路徑是 https:///post ,這個(gè)鏈接可以用來(lái)測(cè)試 POST 請(qǐng)求,它可以返回一些我們剛才請(qǐng)求的信息。
響應(yīng)結(jié)果如下:
{
"args": {},
"data": "",
"files": {},
"form": {
"hello": "world",
"name": "geekdigging"
},
"headers": {
"Accept-Encoding": "identity",
"Content-Length": "28",
"Content-Type": "application/x-www-form-urlencoded",
"Host": "",
"User-Agent": "Python-urllib/3.7"
},
"json": null,
"origin": "218.79.141.143, 218.79.141.143",
"url": "https:///post"
}
從返回的響應(yīng)信息中,我們可以看到請(qǐng)求頭的相關(guān)信息,如我們請(qǐng)求的數(shù)據(jù)類型 Content-Type 為 application/x-www-form-urlencoded ,這個(gè)代表了我們提交數(shù)據(jù)的方式是表單提交,還可以看到請(qǐng)求的來(lái)源 origin 是小編當(dāng)前電腦的 ip 地址,可以看到我們提交的數(shù)據(jù) form 等等的相關(guān)信息。
timeout
timeout 用于設(shè)置超時(shí)時(shí)間,單位為秒。
如果請(qǐng)求超出了設(shè)置的時(shí)間,還未響應(yīng),就會(huì)拋出異常。
我們看個(gè)小示例:
import urllib.request
import urllib.parse
response = urllib.request.urlopen('http:///get', timeout = 1)
print(response.read().decode('utf-8'))
我們先將超時(shí)時(shí)間設(shè)置成為 1s ,看下響應(yīng)結(jié)果:
{
"args": {},
"headers": {
"Accept-Encoding": "identity",
"Host": "",
"User-Agent": "Python-urllib/3.7"
},
"origin": "218.79.141.143, 218.79.141.143",
"url": "https:///get"
}
可以看到是正常響應(yīng)的,我們將超時(shí)時(shí)間設(shè)置為 0.1s ,再看下結(jié)果:
import urllib.request
import urllib.parse
response = urllib.request.urlopen('http:///get', timeout = 0.1)
print(response.read().decode('utf-8'))
已經(jīng)可以看到拋異常出來(lái)了:
Traceback (most recent call last):
...
socket.timeout: timed out
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
...
urllib.error.URLError: <urlopen error timed out>
Process finished with exit code 1
內(nèi)容有些多,小編省略了大量的內(nèi)容。
我們可以看到,這里確實(shí)拋出了超時(shí)的異常,還有同學(xué)記得我們前面講過(guò)的異常處理么,這時(shí)我們可以添加一個(gè)異常處理,將這個(gè)超時(shí)的異常捕獲。
import urllib.request
import urllib.error
import socket
try:
response = urllib.request.urlopen('http:///get', timeout=0.1)
print(response.read().decode('utf-8'))
except urllib.error.URLError as e:
if isinstance(e.reason, socket.timeout):
print('請(qǐng)求超時(shí)啦~~~')
else:
print(e)
結(jié)果如下:
請(qǐng)求超時(shí)啦~~~
證明我們已經(jīng)成功捕獲到了請(qǐng)求超時(shí)的異常。
還有其他的幾個(gè)參數(shù): cafile 、 capath 、 cadefault 用于實(shí)現(xiàn)可信任的 CA 證書(shū)的 HTTP 請(qǐng)求,一般很少使用, context ,用來(lái)實(shí)現(xiàn) SSL 加密傳輸,一般也很少使用。
好了,本篇的內(nèi)容就到這里結(jié)束,希望各位同學(xué)可以自己動(dòng)手敲一下上面的示例代碼。
示例代碼
本系列的所有代碼小編都會(huì)放在代碼管理倉(cāng)庫(kù) Github 和 Gitee 上,方便大家取用。
示例代碼-Github
示例代碼-Gitee
|