Python爬蟲(chóng)原理與基本請(qǐng)求庫(kù)urllib詳解
一、網(wǎng)絡(luò)爬蟲(chóng)是什么?
爬蟲(chóng)的定義:請(qǐng)求網(wǎng)站,并提取數(shù)據(jù)的自動(dòng)化程序。
通過(guò)模擬瀏覽器,按照一定的規(guī)則,自動(dòng)、大批量的獲取網(wǎng)絡(luò)資源,包括文本、圖片、鏈接、音頻、視頻等等。
二、爬蟲(chóng)原理
(講的就是如何獲取網(wǎng)絡(luò)資源的問(wèn)題—怎么爬?要有尊嚴(yán)的爬,坐著就把數(shù)據(jù)優(yōu)雅的爬下來(lái))
1、發(fā)起請(qǐng)求:模擬瀏覽器向目標(biāo)站點(diǎn)發(fā)送一個(gè)request,等待服務(wù)器響應(yīng);
2、獲取響應(yīng)內(nèi)容:如果服務(wù)器能正常響應(yīng),會(huì)返回一個(gè)response,這便是所要獲取的頁(yè)面內(nèi)容
3、解析內(nèi)容:根據(jù)自己的需求,通過(guò)各種解析方法,將得到的內(nèi)容進(jìn)行解析
4、保存數(shù)據(jù):存放于數(shù)據(jù)庫(kù)或者保存為特定格式的文件
所以接下來(lái)本次我們要學(xué)習(xí)的內(nèi)容就是以上這四個(gè)步驟了。
三、基本請(qǐng)求庫(kù)urllib
這個(gè)庫(kù)的作用呢,就是爬蟲(chóng)原理中的第一、二步,向目標(biāo)網(wǎng)站發(fā)送請(qǐng)求用的。
本節(jié)內(nèi)容:
- 用urllib抓取網(wǎng)頁(yè)的基本語(yǔ)法
- 抓取需要輸入關(guān)鍵詞的網(wǎng)頁(yè)
- 抓取需要登錄密碼的網(wǎng)頁(yè)
- 抓取反爬機(jī)制的網(wǎng)頁(yè)
- urllib異常處理
1、用urllib抓取網(wǎng)頁(yè)的【基本語(yǔ)法】
有兩種方法,一種是直接抓取,一種是直接將目標(biāo)網(wǎng)址的網(wǎng)頁(yè)信息保存到本地。
#無(wú)論哪種方法,先導(dǎo)包 import urllib.request
- 方法一:(常用) urllib.request.urlopen(url, data, timeout) 發(fā)送請(qǐng)求直接抓取
''' urllib.request.urlopen(url, data, timeout) 發(fā)送request請(qǐng)求(3個(gè)參數(shù)不需都寫,但必須有url) url:目標(biāo)網(wǎng)址 data:訪問(wèn)url時(shí)發(fā)送的數(shù)據(jù)包,默認(rèn)為null timeout:等待時(shí)長(zhǎng) ''' response = urllib.request.urlopen('http://www.baidu.com/') # decode():解碼,將字節(jié)流格式數(shù)據(jù)以相應(yīng)的形式轉(zhuǎn)化為字符串 print(response.read().decode('utf-8'))
通過(guò)urllib請(qǐng)求后得到的response打印如下:<http.client.HTTPResponse object at 0x000001DA07919608> 所以要先read()讀取出來(lái),但是給我的頁(yè)面都是字節(jié)流數(shù)據(jù),所以我們要在該網(wǎng)頁(yè)源代碼中找到其chartset,比如百度首頁(yè)的編碼格式就是utf-8,所以發(fā)送請(qǐng)求后,要拿到我們可讀的網(wǎng)頁(yè)就需要先read()再decode()解碼。 具體如何找到目標(biāo)網(wǎng)頁(yè)的編碼格式如下圖:
- 方法二: urllib.request.urlretrieve(url,filename) 將目標(biāo)網(wǎng)址網(wǎng)頁(yè)信息保存到本地
''' urllib.request.urlretrieve(url,filename) 直接將目標(biāo)網(wǎng)址的網(wǎng)頁(yè)信息保存到本地 filename:想保存到的路徑文件名 然后用urllib.request.urlcleanup()清除緩存 ''' filename = urllib.request.urlretrieve('http://www.baidu.com/',filename='baidu.html') urllib.request.urlcleanup()
2. 抓取需要輸入【關(guān)鍵詞】的網(wǎng)頁(yè)
背景:我想爬取目標(biāo)網(wǎng)頁(yè)上支持搜索關(guān)鍵詞的網(wǎng)頁(yè)所有相關(guān)信息,比如我想爬百度上所有python的信息,或者疫情的信息,或者其它的信息,如果每次都更換url那就太低效了。 分析網(wǎng)頁(yè)url:目標(biāo)網(wǎng)頁(yè)是百度,//www.baidu.com/,輸入python之后url有變化,發(fā)現(xiàn)//www.baidu.com/s?wd=python這個(gè)網(wǎng)址也能搜索到python的信息,找到規(guī)律,//www.baidu.com/s?wd=后面的詞可以替換成任何詞,都支持搜索,那么我們可以把這個(gè)詞用input來(lái)輸入得到,然后對(duì)url做一個(gè)拼接。 注意:發(fā)現(xiàn)//www.baidu.com/s?wd=后面的詞不支持中文搜索,原因是網(wǎng)址中都是字節(jié)流的數(shù)據(jù),所以如果我們要輸入中文搜索的話,要將中文轉(zhuǎn)為字節(jié)流格式。
# 定義關(guān)鍵詞 keyword = input('輸入你想查詢的關(guān)鍵詞:') # 處理中文,進(jìn)行編碼,轉(zhuǎn)成字節(jié)流格式 keyword = urllib.request.quote(keyword) # url重構(gòu) url = 'http://www.baidu.com/s?wd='+keyword response = urllib.request.urlopen(url).read() # 保存到本地 f = open('baidu_search.html','wb') #wb存儲(chǔ)字節(jié)流數(shù)據(jù),所以上述response不需要用decode解碼 f.write(response) f.close()
3. 抓取需要【登錄密碼】的網(wǎng)頁(yè)
背景:需要爬取用戶登錄之后頁(yè)面的數(shù)據(jù), 這里有一個(gè)url供大家練習(xí)://www.iqianyue.com/mypost/ 該網(wǎng)頁(yè)輸入任何用戶名和密碼都能成功登錄,下圖為登錄后的頁(yè)面,也就是我們這次通過(guò)寫程序要爬取的結(jié)果頁(yè)面。
還記得urllib的基本語(yǔ)法嗎?里面有3個(gè)參數(shù),第二個(gè)是data,也就是我們傳入的值,這里可以把用戶名和密碼跟著頁(yè)面請(qǐng)求一起發(fā)送過(guò)去,但是要怎么做呢?首先要找到網(wǎng)頁(yè)代碼里是怎么設(shè)置用戶名和密碼的命名的(也就是字典里的key值)。
3.1 基礎(chǔ)操作
import urllib.request import urllib.parse #上傳用戶名和密碼,需要先用parse模塊進(jìn)行編碼處理 url = 'https://www.iqianyue.com/mypost/' # urlencode():將上傳的數(shù)據(jù)進(jìn)行編碼處理 # encode():將字符串轉(zhuǎn)化為相應(yīng)編碼的字節(jié)流數(shù)據(jù) postdata = urllib.parse.urlencode({ 'name':'vicky', 'pass':'12345' }).encode('utf-8') response = urllib.request.urlopen(url,data=postdata).read() # 保存網(wǎng)頁(yè) f = open('post.html','wb') f.write(response) f.close()
運(yùn)行成功后將post.html文件打開(kāi),鼠標(biāo)點(diǎn)進(jìn)去后右上角會(huì)顯示各種瀏覽器,選擇各自使用的瀏覽器打開(kāi)頁(yè)面,就會(huì)發(fā)現(xiàn),出現(xiàn)的頁(yè)面就是登錄成功后的頁(yè)面,跟上圖一致。
3.2 設(shè)置cookie
背景:通過(guò)上述常規(guī)方法,可以模擬登錄頁(yè)面抓取該目標(biāo)頁(yè)面的資源,但也存在一種情況,這一步執(zhí)行成功后,后續(xù)如果想抓取該網(wǎng)站的其它網(wǎng)頁(yè),用程序登錄進(jìn)去之后依然是無(wú)登錄狀態(tài),瀏覽器并沒(méi)有留下cookie。
【舉個(gè)栗子】:
import urllib.request import urllib.parse # 主頁(yè)面:'http://blog.chinaunix.net/' # 登錄頁(yè)面:'http://account.chinaunix.net/login?url=http%3a%2f%2fblog.chinaunix.net' # 登錄跳轉(zhuǎn)頁(yè)面:'http://account.chinaunix.net/login/sso?url=http%3A%2F%2Fblog.chinaunix.net' url = 'http://account.chinaunix.net/login/sso?url=http%3A%2F%2Fblog.chinaunix.net' postdata = urllib.parse.urlencode({ 'username':'***', 'password':'******' }).encode('utf-8') response = urllib.request.urlopen(url,postdata).read() f = open('chinaunix.html','wb') f.write(response) f.close()
拿這個(gè)網(wǎng)站舉例,我選的url是登錄跳轉(zhuǎn)時(shí)的頁(yè)面,順利跳轉(zhuǎn)后就進(jìn)入到首頁(yè),如果我后續(xù)再寫一個(gè)請(qǐng)求,直接訪問(wèn)該首頁(yè),登錄進(jìn)去發(fā)現(xiàn)還是無(wú)登錄狀態(tài)。 那么那么那么那么那么…
解決方案;
1、導(dǎo)入cookie處理模塊 http.cookiejar
2、使用http.cookiejar.CookieJar()創(chuàng)建cookiejar對(duì)象
3、使用HTTPCookieProcessor創(chuàng)建cookie處理器,并以此為參數(shù)構(gòu)建opener對(duì)象
4、加載為全局默認(rèn)的opener
這樣寫,就把cookie貫穿整個(gè)網(wǎng)站的始終了,訪問(wèn)哪個(gè)頁(yè)面都是登錄狀態(tài)。
import urllib.request import urllib.parse import http.cookiejar url = 'http://account.chinaunix.net/login/sso?url=http%3A%2F%2Fblog.chinaunix.net' postdata = urllib.parse.urlencode({ 'username':'***', 'password':'***' }).encode('utf-8') response = urllib.request.urlopen(url,postdata).read() # 創(chuàng)建cookiejar對(duì)象 cjar = http.cookiejar.CookieJar() # 創(chuàng)建cookie處理器,并以此為參數(shù)構(gòu)建opener對(duì)象 opener = urllib.request.build_opener(urllib.request.HTTPCookieProcessor(cjar)) # 加載為全局默認(rèn)的opener urllib.request.install_opener(opener) f = open('chinaunix_2.html','wb') f.write(response) f.close()
4. 抓取【反爬機(jī)制】的網(wǎng)頁(yè)
背景:因?yàn)橛行┚W(wǎng)站也有一些反爬機(jī)制,所以你用上述語(yǔ)法進(jìn)行常規(guī)的發(fā)送請(qǐng)求之后不一定能得到響應(yīng),,下面就講述遇到反爬的網(wǎng)站我們應(yīng)該怎么做。
對(duì)于反爬網(wǎng)頁(yè)的對(duì)策有2點(diǎn): headers:設(shè)置頭部信息,將爬蟲(chóng)偽裝成瀏覽器 proxy:設(shè)置代理,使用代理服務(wù)器并經(jīng)常切換代理服務(wù)器
4.1 設(shè)置headers
— headers信息也在網(wǎng)頁(yè)源代碼中,找到User-Agent(headers里一般設(shè)置這個(gè)就行了),構(gòu)建字典,把:后面的系統(tǒng)瀏覽器版本等信息全部復(fù)制粘貼進(jìn)來(lái),模擬瀏覽器登錄。
— 發(fā)送請(qǐng)求前,要先構(gòu)建一個(gè)Request請(qǐng)求對(duì)象,設(shè)置headers,再把請(qǐng)求對(duì)象傳到urlopen中
import urllib.request url = 'http://t.dianping.com/hangzhou' # 構(gòu)建headers h = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36' } # 構(gòu)建Request請(qǐng)求對(duì)象 request = urllib.request.Request(url=url, headers=h) response = urllib.request.urlopen(request).read() # 保存文件 f = open('headers.html','wb') f.write(response) f.close()
4.2 設(shè)置proxy
也就是代理IP,在一定時(shí)間內(nèi)頻繁爬取某個(gè)網(wǎng)頁(yè)可能會(huì)被封,所以可以使用一些代理IP來(lái)爬取資源。
import urllib.request def use_Proxy(proxy_addr,url): # ProxyHandler()設(shè)置對(duì)應(yīng)的代理服務(wù)器信息 proxy = urllib.request.ProxyHandler({'http':proxy_addr}) # build_opener()創(chuàng)建一個(gè)自定義的opener對(duì)象 opener = urllib.request.build_opener(proxy) # 將opener加載為全局使用的opener urllib.request.install_opener(opener) response = urllib.request.urlopen(url).read().decode('utf-8') return response proxy_addr = '183.146.213.157:80' # IP地址:端口號(hào) 自行百度“代理IP” url = 'http://www.taobao.com' print(len(use_Proxy(proxy_addr,url))) #隨便打印一個(gè)長(zhǎng)度,看看這個(gè)代理IP能否使用
5. urllib異常處理
建立異常處理機(jī)制,反饋出錯(cuò)原因。
import urllib.request import urllib.error try: response = urllib.request.urlopen('http://www.ijinqian.com') except urllib.error.URLError as e: print('發(fā)生異常--->'+str(e))
到此這篇關(guān)于Python爬蟲(chóng)原理與基本請(qǐng)求庫(kù)urllib詳解的文章就介紹到這了,更多相關(guān)Python爬蟲(chóng)urllib庫(kù)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python使用Pyinstaller如何打包整個(gè)項(xiàng)目
這篇文章主要介紹了python使用Pyinstaller如何打包整個(gè)項(xiàng)目,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11pytest實(shí)戰(zhàn)技巧之參數(shù)化基本用法和多種方式
本文介紹了pytest參數(shù)化的基本用法和多種方式,幫助讀者更好地使用這個(gè)功能,同時(shí),還介紹了一些高級(jí)技巧,如動(dòng)態(tài)生成參數(shù)名稱、參數(shù)化的組合和動(dòng)態(tài)生成參數(shù)化裝飾器,幫助讀者更靈活地使用參數(shù)化,感興趣的朋友參考下吧2023-12-12

python使用tensorflow保存、加載和使用模型的方法

python3使用matplotlib繪制散點(diǎn)圖

Python實(shí)現(xiàn)的數(shù)據(jù)結(jié)構(gòu)與算法之快速排序詳解

opencv 獲取rtsp流媒體視頻的實(shí)現(xiàn)方法

python?pandas數(shù)據(jù)處理教程之合并與拼接