掃二維碼與項(xiàng)目經(jīng)理溝通
我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流
Python urllib 庫(kù)用于操作網(wǎng)頁(yè) URL,并對(duì)網(wǎng)頁(yè)的內(nèi)容進(jìn)行抓取處理。

本文主要介紹 Python3 的 urllib。
urllib 包 包含以下幾個(gè)模塊:
urllib.request 定義了一些打開(kāi) URL 的函數(shù)和類,包含授權(quán)驗(yàn)證、重定向、瀏覽器 cookies等。
urllib.request 可以模擬瀏覽器的一個(gè)請(qǐng)求發(fā)起過(guò)程。
我們可以使用 urllib.request 的 urlopen 方法來(lái)打開(kāi)一個(gè) URL,語(yǔ)法格式如下:
urllib.request.urlopen(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)
實(shí)例如下:
from
urllib.
request
import urlopen
myURL
= urlopen
(
"https://www.runoob.com/"
)
print
(myURL.
read
(
)
)
以上代碼使用 urlopen 打開(kāi)一個(gè) URL,然后使用 read() 函數(shù)獲取網(wǎng)頁(yè)的 HTML 實(shí)體代碼。
read() 是讀取整個(gè)網(wǎng)頁(yè)內(nèi)容,我們可以指定讀取的長(zhǎng)度:
from
urllib.
request
import urlopen
myURL
= urlopen
(
"https://www.runoob.com/"
)
print
(myURL.
read
(
300
)
)
除了 read() 函數(shù)外,還包含以下兩個(gè)讀取網(wǎng)頁(yè)內(nèi)容的函數(shù):
readline() - 讀取文件的一行內(nèi)容
from urllib.request import urlopen
myURL = urlopen("https://www.runoob.com/")
print(myURL.readline()) #讀取一行內(nèi)容readlines() - 讀取文件的全部?jī)?nèi)容,它會(huì)把讀取的內(nèi)容賦值給一個(gè)列表變量。
from urllib.request import urlopen
myURL = urlopen("https://www.runoob.com/")
lines = myURL.readlines()
for line in lines:
print(line)我們?cè)趯?duì)網(wǎng)頁(yè)進(jìn)行抓取時(shí),經(jīng)常需要判斷網(wǎng)頁(yè)是否可以正常訪問(wèn),這里我們就可以使用 getcode() 函數(shù)獲取網(wǎng)頁(yè)狀態(tài)碼,返回 200 說(shuō)明網(wǎng)頁(yè)正常,返回 404 說(shuō)明網(wǎng)頁(yè)不存在:
import
urllib.
request
myURL1
=
urllib.
request.
urlopen
(
"https://www.runoob.com/"
)
print
(myURL1.
getcode
(
)
)
# 200
try:
myURL2
=
urllib.
request.
urlopen
(
"https://www.runoob.com/no.html"
)
except
urllib.
error.
HTTPError
as e:
if e.
code
==
404:
print
(
404
)
# 404
更多網(wǎng)頁(yè)狀態(tài)碼可以查閱:。
如果要將抓取的網(wǎng)頁(yè)保存到本地,可以使用 函數(shù):
from
urllib.
request
import urlopen
myURL
= urlopen
(
"https://www.runoob.com/"
)
f
=
open
(
"runoob_urllib_test.html"
,
"wb"
)
content
= myURL.
read
(
)
# 讀取網(wǎng)頁(yè)內(nèi)容
f.
write
(content
)
f.
close
(
)
執(zhí)行以上代碼,在本地就會(huì)生成一個(gè) runoob_urllib_test.html 文件,里面包含了 https://www.runoob.com/ 網(wǎng)頁(yè)的內(nèi)容。
更多Python File 處理,可以參閱:
。
URL 的編碼與解碼可以使用 urllib.request.quote() 與 urllib.request.unquote() 方法:
import
urllib.
request
encode_url
=
urllib.
request.
quote
(
"https://www.runoob.com/"
)
# 編碼
print
(encode_url
)
unencode_url
=
urllib.
request.
unquote
(encode_url
)
# 解碼
print
(unencode_url
)
輸出結(jié)果為:
https%3A//www.runoob.com/ https://www.runoob.com/
我們抓取網(wǎng)頁(yè)一般需要對(duì) headers(網(wǎng)頁(yè)頭信息)進(jìn)行模擬,這時(shí)候需要使用到 urllib.request.Request 類:
class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)
import
urllib.
request
import
urllib.
parse
url
=
'https://www.runoob.com/?s='
# 菜鳥(niǎo)教程搜索頁(yè)面
keyword
=
'Python 教程'
key_code
=
urllib.
request.
quote
(
keyword
)
# 對(duì)請(qǐng)求進(jìn)行編碼
url_all
= url+key_code
header
=
{
'User-Agent':
'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
#頭部信息
request
=
urllib.
request.
Request
(url_all
,headers
=header
)
reponse
=
urllib.
request.
urlopen
(request
).
read
(
)
fh
=
open
(
"./urllib_test_runoob_search.html"
,
"wb"
)
# 將文件寫(xiě)入到當(dāng)前目錄中
fh.
write
(reponse
)
fh.
close
(
)
執(zhí)行以上 Python 代碼,會(huì)在當(dāng)前目錄生成 urllib_test_runoob_search.html 文件,打開(kāi) urllib_test_runoob_search.html 文件(可以使用瀏覽器打開(kāi)),內(nèi)容如下:
表單 POST 傳遞數(shù)據(jù),我們先創(chuàng)建一個(gè)表單,代碼如下,我這里使用了 PHP 代碼來(lái)獲取表單的數(shù)據(jù):
import
urllib.
request
import
urllib.
parse
url
=
'https://www.runoob.com/try/py3/py3_urllib_test.php'
# 提交到表單頁(yè)面
data
=
{
'name':
'RUNOOB'
,
'tag' :
'菜鳥(niǎo)教程'
}
# 提交數(shù)據(jù)
header
=
{
'User-Agent':
'Mozilla/5.0 (X11; Fedora; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36'
}
#頭部信息
data
=
urllib.
parse.
urlencode
(data
).
encode
(
'utf8'
)
# 對(duì)參數(shù)進(jìn)行編碼,解碼使用 urllib.parse.urldecode
request
=
urllib.
request.
Request
(url
, data
, header
)
# 請(qǐng)求處理
reponse
=
urllib.
request.
urlopen
(request
).
read
(
)
# 讀取結(jié)果
fh
=
open
(
"./urllib_test_post_runoob.html"
,
"wb"
)
# 將文件寫(xiě)入到當(dāng)前目錄中
fh.
write
(reponse
)
fh.
close
(
)
執(zhí)行以上代碼,會(huì)提交表單數(shù)據(jù)到 py3_urllib_test.php 文件,輸出結(jié)果寫(xiě)入到 urllib_test_post_runoob.html 文件。
打開(kāi) urllib_test_post_runoob.html 文件(可以使用瀏覽器打開(kāi)),顯示結(jié)果如下:
urllib.error 模塊為 urllib.request 所引發(fā)的異常定義了異常類,基礎(chǔ)異常類是 URLError。
urllib.error 包含了兩個(gè)方法,URLError 和 HTTPError。
URLError 是 OSError 的一個(gè)子類,用于處理程序在遇到問(wèn)題時(shí)會(huì)引發(fā)此異常(或其派生的異常),包含的屬性 reason 為引發(fā)異常的原因。
HTTPError 是 URLError 的一個(gè)子類,用于處理特殊 HTTP 錯(cuò)誤例如作為認(rèn)證請(qǐng)求的時(shí)候,包含的屬性 code 為 HTTP 的狀態(tài)碼, reason 為引發(fā)異常的原因,headers 為導(dǎo)致 HTTPError 的特定 HTTP 請(qǐng)求的 HTTP 響應(yīng)頭。
對(duì)不存在的網(wǎng)頁(yè)抓取并處理異常:
import
urllib.
request
import
urllib.
error
myURL1
=
urllib.
request.
urlopen
(
"https://www.runoob.com/"
)
print
(myURL1.
getcode
(
)
)
# 200
try:
myURL2
=
urllib.
request.
urlopen
(
"https://www.runoob.com/no.html"
)
except
urllib.
error.
HTTPError
as e:
if e.
code
==
404:
print
(
404
)
# 404
urllib.parse 用于解析 URL,格式如下:
urllib.parse.urlparse(urlstring, scheme='', allow_fragments=True)
urlstring 為 字符串的 url 地址,scheme 為協(xié)議類型,
allow_fragments 參數(shù)為 false,則無(wú)法識(shí)別片段標(biāo)識(shí)符。相反,它們被解析為路徑,參數(shù)或查詢組件的一部分,并 fragment 在返回值中設(shè)置為空字符串。
from
urllib.
parse
import
urlparse
o
=
urlparse
(
"https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B"
)
print
(o
)
以上實(shí)例輸出結(jié)果為:
ParseResult(scheme='https', netloc='www.runoob.com', path='/', params='', query='s=python+%E6%95%99%E7%A8%8B', fragment='')
從結(jié)果可以看出,內(nèi)容是一個(gè)元組,包含 6 個(gè)字符串:協(xié)議,位置,路徑,參數(shù),查詢,判斷。
我們可以直接讀取協(xié)議內(nèi)容:
from
urllib.
parse
import
urlparse
o
=
urlparse
(
"https://www.runoob.com/?s=python+%E6%95%99%E7%A8%8B"
)
print
(o.
scheme
)
以上實(shí)例輸出結(jié)果為:
https
完整內(nèi)容如下:
|
屬性 |
索引 |
值 |
值(如果不存在) |
|---|---|---|---|
urllib.robotparser 用于解析 robots.txt 文件。
robots.txt(統(tǒng)一小寫(xiě))是一種存放于網(wǎng)站根目錄下的 robots 協(xié)議,它通常用于告訴搜索引擎對(duì)網(wǎng)站的抓取規(guī)則。
urllib.robotparser 提供了 RobotFileParser 類,語(yǔ)法如下:
class urllib.robotparser.RobotFileParser(url='')
這個(gè)類提供了一些可以讀取、解析 robots.txt 文件的方法:
set_url(url) - 設(shè)置 robots.txt 文件的 URL。
read() - 讀取 robots.txt URL 并將其輸入解析器。
parse(lines) - 解析行參數(shù)。
can_fetch(useragent, url) - 如果允許 useragent 按照被解析 robots.txt 文件中的規(guī)則來(lái)獲取 url 則返回 True。
mtime() -返回最近一次獲取 robots.txt 文件的時(shí)間。 這適用于需要定期檢查 robots.txt 文件更新情況的長(zhǎng)時(shí)間運(yùn)行的網(wǎng)頁(yè)爬蟲(chóng)。
modified() - 將最近一次獲取 robots.txt 文件的時(shí)間設(shè)置為當(dāng)前時(shí)間。
crawl_delay(useragent) -為指定的 useragent 從 robots.txt 返回 Crawl-delay 形參。 如果此形參不存在或不適用于指定的 useragent 或者此形參的 robots.txt 條目存在語(yǔ)法錯(cuò)誤,則返回 None。
request_rate(useragent) -以 named tuple RequestRate(requests, seconds) 的形式從 robots.txt 返回 Request-rate 形參的內(nèi)容。 如果此形參不存在或不適用于指定的 useragent 或者此形參的 robots.txt 條目存在語(yǔ)法錯(cuò)誤,則返回 None。
site_maps() - 以 list() 的形式從 robots.txt 返回 Sitemap 形參的內(nèi)容。 如果此形參不存在或者此形參的 robots.txt 條目存在語(yǔ)法錯(cuò)誤,則返回 None。
>>>
import
urllib.
robotparser
>>> rp
=
urllib.
robotparser.
RobotFileParser
(
)
>>> rp.
set_url
(
"http://www.musi-cal.com/robots.txt"
)
>>> rp.
read
(
)
>>> rrate
= rp.
request_rate
(
"*"
)
>>> rrate.
requests
3
>>> rrate.
seconds
20
>>> rp.
crawl_delay
(
"*"
)
6
>>> rp.
can_fetch
(
"*"
,
"http://www.musi-cal.com/cgi-bin/search?city=San+Francisco"
)
False
>>> rp.
can_fetch
(
"*"
,
"http://www.musi-cal.com/"
)
True

我們?cè)谖⑿派?4小時(shí)期待你的聲音
解答本文疑問(wèn)/技術(shù)咨詢/運(yùn)營(yíng)咨詢/技術(shù)建議/互聯(lián)網(wǎng)交流