python網絡爬蟲
靜态網頁爬取概述
靜态網頁介紹
- 在網站設計中,純粹HTML(标準通用标記語言下的一個應用)格式的網頁通常被稱為“靜态網頁”,靜态網頁是标準的HTML檔案,它的檔案擴充名是.htm、.html,可以包含文本、圖像、聲音、FLASH動畫、用戶端腳本和ActiveX控件及JAVA小程式等。(無法實作互動功能)
- 靜态網頁是網站建設的基礎,早期的網站一般都是由靜态網頁制作的。靜态網頁是相對于動态網頁而言,是指沒有背景資料庫、不含程式和不可互動的網頁。動态網頁有資料傳遞的過程,實時更新。靜态網頁相對于動态網頁加載速度更快。
簡單靜态網頁爬取
-
爬蟲進本流程
(1) 發起請求:通過HTTP庫向目标站點發起請求,即發送一個Request,請求可以包含額外的headers等資訊,等待伺服器響應。
(2) 擷取響應内容:如果伺服器能正常響應,會得到一個Response,Response的内容便是所要擷取的頁面内容,類型可能有HTML,Json字元串,二進制資料(如圖檔視訊)等類型。
(3) 解析内容:得到的内容可能是HTML,可以用正規表達式、網頁解析庫進行解析。可能是Json,可以直接轉為Json對象解析,可能是二進制資料,可以做儲存或者進一步的處理。
(4) 儲存資料:儲存形式多樣,可以存為文本,也可以儲存至資料庫,或者儲存特定格式的檔案。
實作HTTP請求
1.使用urllib3庫實作
許多Python的原生系統已經開始使用urllib3庫,其提供了很多python标準庫裡所沒有的重要特性。
連接配接特性 | 連接配接特性 |
---|---|
線程安全 | 管理連接配接池 |
用戶端SSL∕TLS驗證 | 使用分部編碼上傳檔案 |
協助處理重複請求和HTTP重定位 | 支援壓縮編碼 |
支援HTTP和SOCKS代理 | 測試覆寫率達到100% |
(1)生成請求
通過request方法即可建立一個請求,該方法傳回一個HTTP響應對象。Reques文法格式如下。
參數 | 說明 |
---|---|
method | 接收string。表示請求的類型,如“GET”、“HEAD”、“DELETE”等。無預設值 |
url | 接收string。表示字元串形式的網址。無預設值 |
field | 接收dict。表示請求類型所帶的參數。預設為None |
headers | 接收dict。表示請求頭所帶參數。預設為None |
**urlopen_kw | 接收dict或其他Python中的類型的資料。依據具體需要及請求的類型可添加的參數,通常參數指派為字典類型或為具體資料。無預設值 |
import urllib3
http = urllib3.PoolManager()#urllib3必須生成一個執行個體才能進行request請求
request = http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501')
(2)請求頭處理
在request方法中,如果需要傳入headers參數,可通過定義一個字典類型實作。定義一個包含User-Agent資訊的字典,使用浏覽器為火狐和chrome浏覽器,作業系統為“Windows NT 6.1; Win64; x64”,向網站添加連結描述發送帶headers參數的GET請求,hearders參數為定義的User-Agent字典。
import urllib3
http = urllib3.PoolManager()#urllib3必須生成一個執行個體才能進行request請求
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head)
(3)Timeout設定
為防止因為網絡不穩定、伺服器不穩定等問題造成連接配接不穩定時的丢包,可以在請求中增加timeout參數設定,通常為浮點數。依據不同需求,timeout參數提供多種設定方法,可直接在URL後設定該次請求的全部timeout參數,也可分别設定該次請求的連接配接與讀取timeout參數,在PoolManager執行個體中設定timeout參數可應用至該執行個體的全部請求中。
重定向(Redirect)就是通過各種方法将各種網絡請求重新定個方向轉到其它位置(如:網頁重定向、域名的重定向、路由選擇的變化也是對資料封包經由路徑的一種重定向)。
- 方法一直接在url網址後添加
import urllib3
http = urllib3.PoolManager()#urllib3必須生成一個執行個體才能進行request請求
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
timeout=3.0,
headers=head)#逾時超過三秒就終止
- 方法二 使用urllib3内置函數分别設定連接配接和讀取參數
import urllib3
http = urllib3.PoolManager()#urllib3必須生成一個執行個體才能進行request請求
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
timeout=urllib3.Timeout(connect=1.0,read=2.0),
headers=head)#連接配接超過一秒或讀取超過兩秒就終止
- 方法三在設定好的PoolManager執行個體裡進行設定
import urllib3
http = urllib3.PoolManager(timeout=4.0)
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head)
(4)請求重試設定
urllib3庫可以通過設定retries參數對重試進行控制(逾時重試)。預設進行3次請求重試,并進行3次重定向。自定義重試次數通過指派一個整型給retries參數實作,可通過定義retries執行個體來定制請求重試次數及重定向次數。若需要同時關閉請求重試及重定向則可以将retries參數指派為False,僅關閉重定向則将redirect參數指派為False。與Timeout設定類似,可以在PoolManager執行個體中設定retries參數控制全部該執行個體下的請求重試政策。
- 方法一從執行個體的内置函數進行設定
import urllib3
http = urllib3.PoolManager(timeout=4.0,retries=10)#重試十次
head = {'User-Agent':'Windows NT 6.1: Win64: x64'}
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head)
- 方法二在request函數設定參數
http.request('GET',
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501',
headers=head,
retries=10)
(5)生成完整HTTP請求
使用urllib3庫實作生成一個完整的請求,該請求應當包含連結、請求頭、逾時時間和重試次數設定。
User-Agent參數設定可在網頁開發者工具(F12)進行查找。
按F12打開開發者工具,從Network中重新整理檢視參數
import urllib3
#發送請求頭的執行個體
http = urllib3.PoolManager()
#網址
url = 'https://blog.csdn.net/m0_51877411/article/details/116208871?spm=1001.2014.3001.5501'
#請求頭
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36 Edg/90.0.818.46'}
#逾時時間的設定
time = urllib3.Timeout(connect=1.0,read=3.0)
#重試次數和重定向次數設定
request = http.request('GET', url=url ,headers=head, timeout=time, retries=5, redirect=4)
此時就可以生成完整的HTTP請求
接下來可以列印一下伺服器響應碼和響應實體
print('伺服器響應碼:', request.status)
print('響應實體:', request.data)
可以發現中文全部變成\x的編碼方式
可以轉換編碼方式decode()
print('伺服器響應碼:', request.status)
print('響應實體:', request.data.decode('utf-8'))
此時中文可正常顯示
可從網站源代碼meta标簽下檢視編碼方式
2.使用requests庫實作HTTP請求
requests庫是一個原生的HTTP庫,比urllib3庫更為容易使用。requests庫發送原生的HTTP 1.1請求,無需手動為URL添加查詢字串,也不需要對POST資料進行表單編碼。相對于urllib3庫,requests庫擁有完全自動化Keep-alive和HTTP連接配接池的功能(是以不需要去手動給url進行查詢字數的添加以及post資料進行表達編碼,可以直接通過get方法擷取響應實體)。requests庫包含的特性如下。
連接配接特性 | 連接配接特性 | 連接配接特性 |
---|---|---|
Keep-Alive&連接配接池 | 基本∕摘要式的身份認證 | 檔案分塊上傳 |
國際化域名和URL | 優雅的key∕value Cookie | 流下載下傳 |
帶持久Cookie的會話 | 自動解壓 | 連接配接逾時 |
浏覽器式的SSL認證 | Unicode響應體 | 分塊請求 |
自動内容解碼 | HTTP(S)代理支援 | 支援.netrc |
- 使用requests庫實作
-
生成請求
requests庫生成請求的代碼非常便利,其使用的request方法的文法格式如下。
request方法常用的參數及其說明如下。
參數 | 說明 |
---|---|
method | 接收string。表示請求的類型,如“GET”、“HEAD”、“DELETE”等。無預設值 |
url | 接收string。表示字元串形式的網址。無預設值 |
**kwargs | 接收dict或其他Python中的類型的資料。依據具體需要及請求的類型可添加的參數,通常參數指派為字典類型或為具體資料 |
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
rqq = requests.get(url)
print('響應碼:',rqq.status_code)
print('編碼方式:',rqq.encoding)
print('請求頭:',rqq.headers)
print('響應實體:',rqq.content)
print('響應實體:',rqq.text)
此時可以發現中文編碼以\x方式出現
content()和text()比較
print('響應實體:',rqq.content[:40])
print('響應實體:',rqq.text[:40])#列印前四十行
最後傳回的字元串類型有所不同
2. 檢視狀态碼與編碼
- 需要注意的是,當requests庫猜測錯時,需要手動指定encoding編碼,避免傳回的網頁内容解析出現亂碼。
- chardet庫使用detect方法檢測給定字元串的編碼,detect方法常用的參數及其說明如下。
參數 | 說明 |
---|---|
byte_str | 接收string。表示需要檢測編碼的字元串。無預設值 |
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
rqq = requests.get(url)
rqq.encoding = 'utf-8'
print('響應實體:',rqq.text)
此時編碼方式轉換成中文編碼正常顯示
但content()仍以亂碼形式出現
修改content()中文亂碼方式
- 手動指定的方法并不靈活,無法自适應對應爬取過程中不同網頁的編碼,而使用chardet庫比較簡便靈活,chardet庫是一個非常優秀的字元串∕檔案編碼檢測子產品。
import chardet
chardet.detect(rqq.content)#需要輸入為位元組型資料的content,如果輸入text會報錯
>>>import chardet
chardet.detect(rqq.content)#需要輸入為位元組型資料的content,如果輸入text會報錯
import chardet
chardet.detect(rqq.content)#需要輸入為位元組型資料的content,如果輸入text會報錯
>>>{'encoding': 'utf-8', 'confidence': 0.99, 'language': ''}
-
請求頭與響應頭處理
requests庫中對請求頭的處理與urllib3庫類似,也使用headers參數在GET請求中上傳參數,參數形式為字典。使用headers屬性即可檢視伺服器傳回的響應頭,通常響應頭傳回的結果會與上傳的請求參數對應。
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51'}
rqq = requests.get(url, headers=head)
rqq.headers
-
Timeout設定
為避免因等待伺服器響應造成程式永久失去響應,通常需要給程式設定一個時間作為限制,超過該時間後程式将會自動停止等待。在requests庫中通過設定timeout這個參數實作,超過該參數設定的秒數後,程式會停止等待。
import requests
url = 'https://edu.tipdm.org/course/1749/task/42885/show'
head = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.51'}
rqq = requests.get(url, headers=head,timeout=2.0)
rqq.headers
-
生成完整HTTP請求
使用requests庫的request方法向網站“http://www.tipdm.com/tipdm/index.html”發送一個完整的GET請求,該請求包含連結、請求頭、響應頭、逾時時間和狀态碼,并且編碼應正确設定。