urllib:Python爬蟲必學(xué)的網(wǎng)絡(luò)庫,收藏這一篇就Go了

      網(wǎng)友投稿 1374 2025-03-31

      網(wǎng)絡(luò)庫urllib

      urllib庫是Python3內(nèi)置的HTTP請求庫,不需要單獨(dú)安裝,默認(rèn)下載的Python就已經(jīng)包含了該庫。

      urllib庫有4個(gè)模塊:

      request:最基本的HTTP請求模塊,可以用法發(fā)送HTTP請求,并接收服務(wù)器的響應(yīng)數(shù)據(jù),這個(gè)過程就像在瀏覽器地址欄輸入U(xiǎn)RL一樣。

      parse:工具模塊,提供了很多處理URL的API,如拆分、解析、合并等。

      robotparser:用來識別網(wǎng)站的robots.txt文件,然后判斷哪些網(wǎng)站可以抓取,哪些不能抓取。

      error:異常處理。如果出現(xiàn)請求錯(cuò)誤,可以捕獲這些異常,然后根據(jù)代碼的需要,進(jìn)行處理。

      下面,我們來分別介紹urllib庫這4個(gè)模塊。

      request

      request模塊,包含發(fā)送請求,獲得響應(yīng),Cookie,代理等相關(guān)API。這里,我們分別來介紹其使用的方式。

      發(fā)送GET請求

      首先,我們一般進(jìn)行爬蟲程序編寫時(shí),開始都需要發(fā)送請求,然后獲得響應(yīng)進(jìn)行處理。比如通過GET請求獲取網(wǎng)頁源代碼,示例如下:

      import urllib.request response=urllib.request.urlopen("https://www.csdn.net/") print(response.read().decode("UTF-8"))

      如上面代碼所示,運(yùn)行之后,我們會得到網(wǎng)頁html源代碼。

      這里response是一個(gè)HTTPResponse對象,調(diào)用它多種方法及其屬性,就可以進(jìn)行多樣的處理。

      比如,我們這里來獲取CSDN首頁,調(diào)用其屬性及其方法,示例如下:

      import urllib.request response = urllib.request.urlopen("https://www.csdn.net/") print("status:", response.status, " msg:", response.msg, " version:", response.version) print(response.getheaders())

      這里,我們輸出了CSDN首頁的響應(yīng)狀態(tài)碼,響應(yīng)消息以及HTTP版本的屬性,同時(shí)也打印其完整的響應(yīng)頭信息。

      發(fā)送POST請求

      默認(rèn)request.urlopen()函數(shù)發(fā)送的GET請求,如果需要發(fā)送POST請求,我們需要使用data命令參數(shù),該參數(shù)類型是bytes。示例代碼如下:

      import urllib.request import urllib.parse data = bytes(urllib.parse.urlencode({'username': 'name', 'age': '123456'}), encoding="UTF-8") response = urllib.request.urlopen("http://httpbin.org/post", data=data) print(response.read().decode("UTF-8"))

      運(yùn)行之后,如果請求成功就會返回一大堆字符串?dāng)?shù)據(jù)。

      請求超時(shí)處理

      在實(shí)際的爬蟲項(xiàng)目中,我們都需要考慮一個(gè)關(guān)鍵的問題,那就是請求超時(shí)。如果請求網(wǎng)址因?yàn)殚L時(shí)間沒有響應(yīng),那么卡在這里往往浪費(fèi)大量的資源。

      所以,我們需要設(shè)置一個(gè)超時(shí)時(shí)間,如果在限定的時(shí)間沒有響應(yīng),就應(yīng)該重新抓取,或者不在抓取。示例代碼如下:

      import urllib.request import urllib.parse import urllib.error import socket data = bytes(urllib.parse.urlencode({'username': 'name', 'age': '123456'}), encoding="UTF-8") try: response = urllib.request.urlopen("http://httpbin.org/post", data=data, timeout=0.1) print(response.read().decode("UTF-8")) except urllib.error.URLError as e: if isinstance(e.reason,socket.timeout): print("超時(shí)處理") finally: print("繼續(xù)爬蟲的工作")

      爬蟲偽裝

      現(xiàn)在只要是知名的網(wǎng)站,都具有定義的防爬蟲技術(shù)。所以,我們在開發(fā)爬蟲程序時(shí),需要將自己的請求偽裝成瀏覽器。

      不過,urlopen()并沒有header請求頭參數(shù),我們需要使用request.Request()進(jìn)行構(gòu)造請求,示例代碼如下:

      import urllib.request import urllib.parse data = bytes(urllib.parse.urlencode({'username': 'name', 'age': '123456'}), encoding="UTF-8") headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36' } req = urllib.request.Request("http://httpbin.org/post", data=data, headers=headers) response = urllib.request.urlopen(req) print(response.read().decode("UTF-8"))

      這里,我們將爬蟲程序偽裝成從火狐瀏覽器進(jìn)行的請求。

      當(dāng)然,Request類還有許多其他的信息,下表是博主列出來供讀者參考使用的。

      需要注意的是最后一個(gè)參數(shù)method,如果你在程序中,即指定了請求是GET,同時(shí)也有data表單數(shù)據(jù),那么默認(rèn)表單不會提交給服務(wù)器。

      代理

      其實(shí),服務(wù)器除了根據(jù)請求頭進(jìn)行判斷是否為爬蟲之外,最簡單判別爬蟲的方式,就是判斷是否是同一個(gè)IP短時(shí)間大量訪問。

      如果同一個(gè)IP短時(shí)間大量訪問,那么可以直接判別為爬蟲程序。而這個(gè)時(shí)候,我們可以通過代理進(jìn)行偽裝。當(dāng)然,使用代理時(shí)應(yīng)該不斷更換代理服務(wù)器

      示例代碼如下:

      import urllib.error from urllib.request import ProxyHandler, build_opener proxy_handler = ProxyHandler({ 'http': 'http://183.47.138.80:8888', 'http': 'http://125.78.226.217:8888' }) opener = build_opener(proxy_handler) try: response = opener.open('https://www.csdn.net/') print(response.read().decode('UTF-8')) except urllib.error.URLError as e: print(e.reason)

      運(yùn)行之后,與前文一樣返回CSDN首頁的源代碼。不過,需要注意的是,博主在寫博客時(shí),這個(gè)代碼IP是有效的,但如果你讀到這篇博文,可能已經(jīng)失效了,你需要自己取找免費(fèi)的代理服務(wù)器取測試。

      獲取Cookie

      一般來說,當(dāng)我們使用爬蟲登錄網(wǎng)站之后,會使用服務(wù)器返回的Cookie進(jìn)行操作,有了這個(gè)Cookie,服務(wù)器就知道我們已經(jīng)登錄過。

      那么如果獲取Cookie數(shù)據(jù)呢?示例如下:

      import urllib.error from urllib.request import ProxyHandler import http.cookiejar cookie = http.cookiejar.CookieJar() handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) try: response = opener.open('https://www.csdn.net/') for item in cookie: print("name=", item.name, " value=", item.value) except urllib.error.URLError as e: print(e.reason)

      如上面代碼所示,我們可以通過http.cookiejar庫進(jìn)行操作,這里會返回cookie的鍵值對,并輸出打印,效果如下:

      如果本身網(wǎng)站的Cookie時(shí)效比較長的話,那么一次爬蟲之后,我們可以將其保存在使用,這個(gè)時(shí)候會用到MozillaCookieJar類與LWPCookieJar類。

      這2個(gè)類會在獲取Cookie的同一時(shí)間,將Cookie分別保存為Mozilla瀏覽器格式和libwww-perl(LWP)格式。示例代碼如下:

      import urllib.error from urllib.request import ProxyHandler import http.cookiejar cookie = http.cookiejar.MozillaCookieJar('cookies.txt') handler = urllib.request.HTTPCookieProcessor(cookie) opener = urllib.request.build_opener(handler) try: response = opener.open('https://www.csdn.net/') cookie.save(ignore_discard=True,ignore_expires=True) except urllib.error.URLError as e: print(e.reason)

      運(yùn)行之后,會生成一個(gè)cookies.txt文件,具體內(nèi)容如下:

      而LWPCookieJar類的使用方式與上面MozillaCookieJar類似,這里不在贅述。至于讀取通過cookie.load()方法進(jìn)行加載Cookie。

      Parse

      在實(shí)際的爬蟲處理中,我們經(jīng)常會遇到各種的編碼問題。而這些問題就可以通過Parse進(jìn)行解決處理。

      中文的編碼與解碼

      比如,在某些網(wǎng)址的請求頭中,有些網(wǎng)站請求頭會含有中文。但默認(rèn)不進(jìn)行任何處理肯定會報(bào)UnicodeEncodeError錯(cuò)誤。

      讀者可以通過上面的代碼,在headers字典中添加一個(gè)鍵值對,值是中文試試。下面,我們需要對其進(jìn)行編碼,示例如下:

      import urllib.parse import base64 value = urllib.parse.urlencode({'name': '安踏'}) print("編碼后的中文:", value) print("解碼后的中文:", urllib.parse.unquote(value)) #base64編碼與解碼 base64Value=base64.b64encode(bytes('學(xué)習(xí)網(wǎng)絡(luò)urllib庫',encoding="UTF-8")) print("編碼后的中文:", base64Value) print("解碼后的中文:", str(base64.b64decode(base64Value),"UTF-8"))

      運(yùn)行之后,效果如下:

      需要注意的是,urlencode只能對url參數(shù)進(jìn)行編碼,比如這里對headers請求頭進(jìn)行了編碼。而網(wǎng)站中的數(shù)據(jù),有的是通過base64進(jìn)行編碼的,這個(gè)時(shí)候,我們也需要掌握base64的解碼與編碼。

      quote與unquote

      quote函數(shù)也是一個(gè)編碼函數(shù),但它與urlencode不同,urlencode只能對URL進(jìn)行編碼。而quote可以給任意字符串進(jìn)行編碼。

      至于unquote是編碼的逆過程(解碼),示例如下:

      from urllib.parse import quote, unquote url = 'https://www.baidu.com/s?wd=' + quote("王者榮耀") print(url) url = unquote(url) print(url)

      運(yùn)行之后,效果如下:

      URL解析

      在前面介紹的時(shí)候,我們也說了parse模塊可以分解,分析,合并URL。下面,我們來通過這些函數(shù),舉一些列子,讀者就會明白了。

      from urllib import parse url = 'https://www.csdn.net/' split_result=parse.urlsplit(url); print(split_result) result = parse.urlparse(url) print('scheme:', result.scheme) # 網(wǎng)絡(luò)協(xié)議 print('netloc:', result.netloc) # 域名 print('path:', result.path) # 文件存放路徑 print('query:', result.query) # 查詢字符 print('fragment:', result.fragment) # 拆分文檔中的特殊貓

      運(yùn)行之后,效果如下:

      連接URL

      對于URL來說,有時(shí)候我們需要將URL的多個(gè)部分進(jìn)行組合。比如,我們在爬取某一個(gè)網(wǎng)站下圖片時(shí),其默認(rèn)的前部分基本都相同,可能只是ID不同。

      那么這個(gè)時(shí)候,我們需要將前部分URL與ID進(jìn)行拼接。示例代碼如下:

      import urllib.parse print(urllib.parse.urljoin('https://blog.csdn.net','liyuanjinglyj')) print(urllib.parse.urljoin('https://blog.csdn.net','https://www.baidu.com')) print(urllib.parse.urljoin('https://blog.csdn.net','index.html')) print(urllib.parse.urljoin('https://blog.csdn.net/index.php','?name=30'))

      運(yùn)行之后,效果如下:

      如果第2個(gè)參數(shù)不是一個(gè)完整的URL,會將第2個(gè)參數(shù)的值加到第1個(gè)參數(shù)的后面,自動(dòng)添加斜杠"/”。

      如果第2個(gè)參數(shù)是一個(gè)完整的URL,那么直接返回第2個(gè)URL。

      參數(shù)轉(zhuǎn)換(parse_qs與parse_qsl)

      parse_qs函數(shù)將多個(gè)參數(shù)拆成字典的形式,key是參數(shù)名,value是參數(shù)值。

      而parse_qsl函數(shù)返回一個(gè)列表,每個(gè)元素是一個(gè)包含2個(gè)元素值的元組,第1個(gè)元素表示key,第2個(gè)元素表示value。

      示例如下:

      from urllib.parse import parse_qs, parse_qsl query = "name=李元靜&age=29" print(parse_qs(query)) print(parse_qsl(query))

      運(yùn)行之后,效果如下:

      2個(gè)函數(shù)僅返回的參數(shù)形式不同,內(nèi)容基本都是匹配的。同時(shí),它們2個(gè)函數(shù)不管對什么類型,轉(zhuǎn)換結(jié)果都是字符串。

      Robots協(xié)議

      Robots協(xié)議也稱為爬蟲協(xié)議、機(jī)器人協(xié)議,它的全名是網(wǎng)絡(luò)爬蟲排除標(biāo)準(zhǔn)(Robots Exclusing Protocol)。

      用來告訴爬蟲和搜索引擎哪些頁面可以抓取,哪些不可以抓取。該協(xié)議通常放在一個(gè)名為robots.txt的文本文件中,它位于網(wǎng)站的根目錄下。

      特別注意,robots.txt文件僅僅是為了告訴開發(fā)中哪些數(shù)據(jù)可以抓取,哪些數(shù)據(jù)不可以,并不能阻止開發(fā)中進(jìn)行爬蟲操作。但作為一個(gè)有良知的程序員,應(yīng)盡量尊重這些規(guī)則。

      Robots協(xié)議的定義規(guī)則

      robots.txt的文本文件一般有3個(gè)值:

      User-agent:如果它為*,表示對所有爬蟲有效

      Disallow:哪個(gè)目錄下的資源不能抓取,比如Disallow:/index/,那么禁止爬取index文件中的所有資源。如果為/,表示該網(wǎng)站都不能抓取。

      urllib:Python爬蟲必學(xué)的網(wǎng)絡(luò)庫,收藏這一篇就Go了

      Allow:表示哪個(gè)目錄下的資源可以抓取。比如Allow:/,表示所有網(wǎng)站都可以抓取。值與Disallow一樣,只是反意義。

      當(dāng)然,User-agent還可以禁止某些爬蟲抓取,比如禁止百度爬蟲抓取:User-agent:BaiduSpider。常用的爬蟲名如下表:

      Robots協(xié)議的解析

      當(dāng)然,我們獲取Robots協(xié)議,肯定是為了獲取哪些資源不可爬。但是,直接通過字符串進(jìn)行解析雖然也能完成,不過稍微復(fù)雜了點(diǎn)。

      而urllib庫的robotparser模塊提供了相應(yīng)的API進(jìn)行解析,也就是RobotFileParser類。示例如下:

      from urllib.robotparser import RobotFileParser #一種解析方式 robot = RobotFileParser() robot.set_url('https://www.csdn.net/robots.txt') robot.read() print(robot.can_fetch('*', 'https://blog.csdn.net/rank/list')) #另一種解析方式 robot = RobotFileParser('https://www.csdn.net/robots.txt') print(robot.can_fetch('*', 'https://blog.csdn.net/rank/list'))

      這里,can_fetch方法用來判斷該網(wǎng)址根據(jù)Robots協(xié)議是否可以抓取。這里判斷的是CSDN排行榜能否抓取,返回了True。

      error

      異常處理在上面的代碼中,我們已經(jīng)用過了。比如在請求超時(shí)的講解之中,我們用到了URLError。但是它還有一個(gè)子類HTTPError。

      HTTPError

      它主要用于HTTP請求錯(cuò)誤的處理,比如400,404等錯(cuò)誤。

      HTTPError有3個(gè)重要的參數(shù):

      code:服務(wù)器返回的狀態(tài)碼,如404等

      reason:返回錯(cuò)誤的原因

      headers:返回請求頭

      不過,HTTPError不能捕獲超時(shí)錯(cuò)誤,如果你需要處理超時(shí)錯(cuò)誤,那么只能通過URLError進(jìn)行捕獲。

      HTML Python 爬蟲

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      版權(quán)聲明:本文內(nèi)容由網(wǎng)絡(luò)用戶投稿,版權(quán)歸原作者所有,本站不擁有其著作權(quán),亦不承擔(dān)相應(yīng)法律責(zé)任。如果您發(fā)現(xiàn)本站中有涉嫌抄襲或描述失實(shí)的內(nèi)容,請聯(lián)系我們jiasou666@gmail.com 處理,核實(shí)后本網(wǎng)站將在24小時(shí)內(nèi)刪除侵權(quán)內(nèi)容。

      上一篇:EXCEL怎么按顏色進(jìn)行排序
      下一篇:WPS表使用查找和替換功能在大量數(shù)據(jù)中查找替換內(nèi)容(wps表格的查找替換功能在哪里)
      相關(guān)文章
      亚洲a视频在线观看| 国产午夜亚洲精品理论片不卡 | 亚洲白色白色在线播放| 毛片亚洲AV无码精品国产午夜| 99久久婷婷国产综合亚洲| 亚洲一区二区三区影院 | 亚洲AV网一区二区三区| 亚洲AV无码国产一区二区三区| 亚洲日本一线产区和二线| 国产99在线|亚洲| 亚洲av无码一区二区三区天堂古代 | 99亚洲精品高清一二区| 久久精品亚洲中文字幕无码麻豆| 久久夜色精品国产嚕嚕亚洲av| 国产亚洲精久久久久久无码| 久久久久久A亚洲欧洲AV冫| 中文亚洲AV片在线观看不卡 | 亚洲黄色在线观看网站| 亚洲性色高清完整版在线观看| 久久久久亚洲AV成人片| 亚洲大片免费观看| 国产亚洲精品VA片在线播放| 最新亚洲精品国偷自产在线| 亚洲中文无码mv| 亚洲AV无码成人网站在线观看 | 久久亚洲熟女cc98cm| 亚洲中字慕日产2020| 在线a亚洲老鸭窝天堂av高清| 亚洲狠狠婷婷综合久久蜜芽| 国产区图片区小说区亚洲区| 亚洲男人av香蕉爽爽爽爽| 亚洲真人日本在线| 久久精品亚洲乱码伦伦中文| 国产亚洲一区二区三区在线观看| 国产亚洲一区二区在线观看| 水蜜桃亚洲一二三四在线| 777亚洲精品乱码久久久久久 | 亚洲国模精品一区| 亚洲一级特黄大片在线观看| a级亚洲片精品久久久久久久 | 国产精品亚洲一区二区在线观看|