六星源課堂:Python網(wǎng)絡(luò)爬蟲基礎(chǔ)——Urllib庫
Urllib庫簡(jiǎn)介
Urllib庫是Python的標(biāo)準(zhǔn)庫,提供了一系列用于操作URL的功能,其大部分功能與Requests庫類似,也有一些特別的用法。它的API并不像Requests那樣直觀簡(jiǎn)潔,所以小編在這里只簡(jiǎn)要地介紹一下Urllib庫的使用方法,讓讀者知道這個(gè)庫的用法,后面的爬蟲實(shí)例還是以Requests庫作為編寫簡(jiǎn)單爬蟲的主要工具。
Urllib庫是Python標(biāo)準(zhǔn)庫提供的一個(gè)用戶操作URL的模塊,Python 3把原來Python 2的Urilib庫和Urllib 2庫合并成了一個(gè)Urllib庫,現(xiàn)在講解的就是Python 3中的Urllib庫。
Urllib庫含有4個(gè)模塊,主要作用如下:
urllib.request——打開和讀取URL;
urllib.error——包含Urllib.request各種錯(cuò)誤的模塊;
urlib.parse——解析URL;
urllib.robotparse——解析網(wǎng)站robots.txt文件。
urllib.request模塊用得最多,這里將著重講解。urllib.parse模塊擁有與Requests庫不同的、特別的用處,這里也簡(jiǎn)單介紹一下。
發(fā)送GET請(qǐng)求
下面來看如何使用Urllib庫發(fā)送GET請(qǐng)求。例如,要抓取豆瓣的首頁并打印響應(yīng)內(nèi)容。
>>>from urllib.request import urlopen
>>>html = urlopen('https://www.douban.com/')
>>>response = html.read()
>>>print(response)
這里首先從urllib.request模塊引入urlopen函數(shù),然后使用這個(gè)函數(shù)向豆瓣首頁發(fā)送請(qǐng)求,它會(huì)返回一個(gè)二進(jìn)制的對(duì)象html,對(duì)這個(gè)html對(duì)象進(jìn)行read()操作,可以得到一個(gè)包含網(wǎng)頁內(nèi)容的二進(jìn)制響應(yīng)(response),最后打印出這個(gè)response。也可以對(duì)返回響應(yīng)解碼(decode),打印響應(yīng)的文本內(nèi)容。
>>>print(response.decode('utf-8'))
這里對(duì)response使用utf-8解碼,獲取到了它的文本內(nèi)容。
也可以像Requests庫那樣傳遞URL參數(shù),例如,還是要在豆瓣的書籍欄目中查詢與Python相關(guān)的內(nèi)容,可以使用如下代碼。
>>>import urllib.request
>>>import urllib.parse
>>>payload = {'q': 'python', 'cat': '1001'}
#這里需要對(duì)傳遞的URL參數(shù)進(jìn)行編碼
>>>payload_encode = urllib.parse.urlencode(payload)
>>>request_url = 'https://www.douban.com/search'
#構(gòu)造請(qǐng)求的URL地址,添加參數(shù)到URL后面
>>>request_url += '?' + payload_encode
#發(fā)起請(qǐng)求
>>>response = urllib.request.urlopen(request_url)
#使用UTF-8解碼并打印響應(yīng)的文本
>>>print(response.read().decode('utf-8'))
注意這里與Requests不同,要對(duì)傳遞的URL參數(shù)進(jìn)行編碼,所以需要引入urllib.parse模塊對(duì)payload進(jìn)行編碼,然后構(gòu)造請(qǐng)求的URL地址??梢源蛴〕鰟倓倶?gòu)造的URL看一下。
>>>print(request_url)
https://www.douban.com/search?q=python&cat=1001
從上面?zhèn)鬟fURL參數(shù)發(fā)起請(qǐng)求的過程不難看出,Urllib庫在使用方面沒有Requests庫那么直觀和簡(jiǎn)單,需要編寫更多的代碼才能達(dá)到與Requests相同的結(jié)果。
也可以在response上使用geturl()獲取當(dāng)前所爬取的URL地址。
>>>print(response.geturl())
https://www.douban.com/search?q=python&cat=1001
還可以使用getcode()查看爬取網(wǎng)頁的狀態(tài)碼。
>>>print(response.getcode())
200
模擬瀏覽器發(fā)送GET請(qǐng)求
與Requests庫一樣,Urllib庫允許設(shè)置一些Headers信息,模擬成瀏覽器去訪問網(wǎng)站,從而避免被服務(wù)器反爬蟲禁止。如果想偽裝成瀏覽器發(fā)送GET請(qǐng)求,就需要使用Request對(duì)象,通過往Request對(duì)象添加HTTP請(qǐng)求頭部,就可以把請(qǐng)求偽裝成瀏覽器。偽裝成Chrome瀏覽器爬取豆瓣首頁的示例如下。
>>>import urllib.request
>>>import urllib.parse
>>>url = 'https://www.douban.com/'
#定義headers
>>>headers = {'User-Agent': 'Mozilla/5.0 (Windows NT \
10.0;WOW64) AppleWebKit/537.36 (KHTML, like \
Gecko) Chrome/46.0.2490.80 Safari/537.36'}
#創(chuàng)建request對(duì)象并添加headers
>>>request = urllib.request.Request(url,
headers = headers)
>>>response = urllib.request.urlopen(request).read()
上面的代碼首先設(shè)置要爬取的網(wǎng)址和請(qǐng)求頭部,然后調(diào)用urllib.request.Request()函數(shù)創(chuàng)建一個(gè)request對(duì)象,該函數(shù)傳入請(qǐng)求URL和請(qǐng)求頭部,請(qǐng)求頭部使用參數(shù)headers,它有默認(rèn)值,默認(rèn)是不傳任何頭部。這時(shí)已經(jīng)成功設(shè)置好報(bào)頭,然后使用urlopen方法打開該Request對(duì)象即可打開對(duì)應(yīng)的網(wǎng)址。這里為了防止網(wǎng)頁長(zhǎng)時(shí)間未響應(yīng),可以設(shè)置超時(shí)的時(shí)間值??梢栽趗rllib.request.urlopen打開網(wǎng)址的時(shí)候,通過添加timeout字段進(jìn)行設(shè)置。
>>>response = urllib.request.urlopen(request, timeout=3).read()
POST發(fā)送一個(gè)請(qǐng)求
如果要POST發(fā)送一個(gè)請(qǐng)求,只需要把參數(shù)data以bytes形式傳入即可。例如這里向http://httpbin.org/post這個(gè)網(wǎng)址POST一個(gè)dict數(shù)據(jù),然后查看它的響應(yīng)。
>>>from urllib import request, parse
#首先對(duì)數(shù)據(jù)進(jìn)行轉(zhuǎn)碼
>>>post_data = parse.urlencode([('key1', 'value1'),
('key2', 'value2')])
#創(chuàng)建request對(duì)象
>>>url = request.Request('http://httpbin.org/post')
#添加headers
>>>url.add_header('User-Agent','Mozilla/5.0 (Windows NT \
10.0;WOW64) AppleWebKit/537.36 (KHTML, \
like Gecko) Chrome/46.0.2490.80 Safari/537.36')
>>>response = request.urlopen(url,
data=post_data.encode('utf-8')).read()
可以打印response查看,會(huì)發(fā)現(xiàn)它返回了剛剛POST的數(shù)據(jù)。
URL解析
Urllib.parse提供了幾個(gè)可以用來為爬蟲提供URL解析的工具,這幾個(gè)工具是Requests庫所沒有的。
1. urlparse:拆分URL
urlparse模塊會(huì)將一個(gè)普通的URL解析為6個(gè)部分,返回的數(shù)據(jù)類型都是元組。返回的6個(gè)部分分別是scheme(機(jī)制)、netloc(網(wǎng)絡(luò)位置)、path(路徑)、params(路徑段參數(shù))、query(查詢)、fragment(片段)。
示例如下。
>>>from urllib.parse import urlparse
>>>urlparse('https://www.douban.com/search?cat=1001&q=python')
ParseResult(scheme='https',
netloc='www.douban.com', path='/search',
params='', query='cat=1001&q=python',
fragment='')
2. urlunparse:拼接URL
urlunparse可以拼接URL,為urlparse的反向操作,它可以將已經(jīng)分解后的URL再組合成一個(gè)URL地址,示例如下。
>>>from urllib.parse import urlunparse
>>>data = ['https', 'www.douban.com',
'/search', '', 'cat=1001&q=python', '']
>>>print(urlunparse(data))
https://www.douban.com/search?cat=1001&q=python
3. urljoin:拼接兩個(gè)URL
urljoin這個(gè)函數(shù)可以很方便地拼接URL,示例如下。
>>>from urllib.parse import urljoin
>>>urljoin('https://www.douban.com', 'accounts/login')
https://www.douban.com/accounts/login
>>>urljoin('https://www.douban.com', '/accounts/login')
https://www.douban.com/accounts/login
>>>urljoin('https://www.douban.com/accounts/', '/accounts/login')
https://www.douban.com/accounts/login
可以看到,urljoin這個(gè)函數(shù)會(huì)自行判斷兩個(gè)URL之間是否有/或重復(fù)的路徑,從而拼接成正確的URL。在構(gòu)造爬蟲URL時(shí),有時(shí)候會(huì)用到urljoin這個(gè)函數(shù)構(gòu)造爬蟲URL的完整路徑。
以上為本次分享的全部?jī)?nèi)容,如果對(duì)編程想獲得更多了解,請(qǐng)前往六星源課堂,開啟你的編程之旅~