爬蟲
爬蟲開篇
何為爬蟲?
爬蟲是通過編寫程序,模擬瀏覽器,對互聯網數據進行抓取的過程
爬蟲的應用場景
- 通用爬蟲 :抓取系統的重要組成部分,抓取的是一整張頁面數據
- 聚焦爬蟲 :建立在通用爬蟲的基礎上 ,抓取的是頁面中的特定的局部內容
- 增量式爬蟲 :檢查網站中數據更新的情況,只會抓取網站中最新的數據
爬蟲的矛與盾
- 反爬機制 : 門戶網站,可以通過指定相應的策略或者技術手段,防止爬蟲程序進行網站數據的爬取
- 反反爬策略 : 爬蟲程序可以通過指定相關的策略或者技術手段,破解門戶網站中的反爬機制,從而可以獲取門戶網站的數據
robots.txt協議
- 定義:也稱君子協議。規定了網站中那些數據可以被爬蟲爬取,哪些禁止爬取
- 查看方式: 在訪問網站后加上rebots.txt即可看到。例如:
Http協議
概念:服務端和客戶端進行數據交互的一種形式
常用請求頭信息:
- User-Agent :請求載體的身份標識
- Contention :請求完畢后,設定是否斷開鏈接
常用響應頭信息:
- Content-Type :服務端響應客戶端的數據類型
HTTPS協議
Http在數據傳輸過程是明文狀態的,為了保證數據的安全性,創建了HTTPS協議
兩者的區別就是:http數據未加密狀態,https數據是加密狀態
加密方式:
- 對稱秘鑰加密 :
- 秘鑰 :公開秘鑰
- 加密過程 :
- 客戶端和服務端約定同一種加密方式,客戶端加密數據之后,把秘鑰和數據要一起發送給服務端,服務端會根據秘鑰進行解密
- 優缺點:
- 優點:一定程度上保證了數據的安全性
- 缺點:發送秘鑰時,容易被劫持,所以無法根本上還是無法保證數據的安全性
- 非對稱秘鑰加密 :
- 秘鑰:
- 私有秘鑰
- 公開秘鑰
- 加密過程:
- 服務端告訴客戶端自己的加密方式,即公開秘鑰。客戶端通過公開秘鑰加密發送給服務端之后,服務端會根據私有秘鑰進行解密
- 優缺點:
- 優點:保證了數據的安全性
- 缺點:
- 不能保證接受端向發送端發送的秘鑰就是預先發送的, 因為只要發送秘鑰就有被劫持的風險
- 由于每次傳輸都需要加密解密,降低了通信速度
- 秘鑰:
- 證書秘鑰加密 :
- 數字證書加密
- 加密過程:
- 服務端開發者攜帶公鑰向可信任的數字證書認證機構提出公開秘鑰的申請 ,認證機構在審核申請者的身份之后,對開發者提供的公開秘鑰進行數字簽名,然后將已簽名的公開秘鑰與數字證書綁定到一起。
- 服務端向客戶端發送數字證書,客戶端通過數字證書中的數字簽名來驗證公鑰的真偽,驗證通過之后客戶端就會對報文通過公鑰進行加密傳輸,服務端接受到之后使用自己的私鑰進行解密
- 一般認證機構都是信任度高的,所以基本不會出現證書偽造情況。
Requests模塊
常用方法:
-
requests.text:獲取requests 的字符串類型的文本內容
-
requests.json():獲取requests的json類型的文本內容
請求方式:
- requests.get(url, params, headers)
- requests.post(url, data, headers)
數據分析
1. 正則解析
re_path = '<div class="recmd-right"><a .*? href="(.*?)" target.*?</div>' # href="/article/123124303" article_href_list = re.findall(re_path, page_html, re.S)
2. BeautifulSoup
安裝
pip install bs4 # 安裝bs4 from bs4 import BeautifulSoup 導入BeautifulSoup
入門使用
1. 實例化
- 實例化本地對象
- fp = open() soup = BeautifulSoup(fp, "lxml") # fp為文件句柄 lxml為固定參數
- 實例化網頁
- BeautifulSoup(html, "lxml")
示例:
# 本地文件: fp = open(" example", "lxml:) soup = BeautifulSoup(fp, "lxml") # 網頁 soup = BeautifulSoup(page_html, "lxml")
2. 常用方法調用
1. 使用TagName定位
# 使用標簽tagName定位 返回文檔中第一個標簽 print(soup.title) # <title>測試bs4</title> print(soup.a) # <a ></a>
2. find() 方法
# 獲取類屬性為content的div print(soup.find("div", class_="content")) # 獲取上述div中的 文本 print(soup.find("div", class_="content").text) # 天地悠悠 ex # 獲取上述div中的a標簽文本 print(soup.find("div", class_="content").a.text) # ex
3. find_all() 方法
# find_all方法 # 返回多個數據 以列表的形式 print(soup.find_all("a"))
4. select() 方法
# select方法 層級選擇 以列表的形式返回多個數據 # 單個層級選擇 print(soup.select(".content >span >a")) # [<a href="ex.html"> ex </a>, <a href="qiutuimg.py"> qiutuimg </a>] # 多個層級選擇 即跨級選擇 print(soup.select(".content a")) # [<a href="ex.html"> ex </a>, <a href="qiutuimg.py"> qiutuimg </a>]
5. 獲取標簽中的文本數據
# 獲取標簽中的文本數據 print(soup.div.text) # 搜狗 360 百度 谷歌 print(soup.div.get_text()) # 同上 print(soup.div.string) # None ''' 三者的區別: text/get_text() 可以獲取標簽內的 string 只會獲取直系文本 '''
6. 獲取標簽中的屬性值
# 獲取標簽中的屬性值 print(soup.select(".content >span >a")[0]["href"]) # ex.html
3. xpath 解析
解析原理:
- 實例化一個etree對象,將需要被解析的頁面源碼數據加載到該對象中
- 調用etree對象的xpath方法結合xpath表達式實現標簽的定位和內容的獲取
解析器:
pip install lxml
實例化對象:
- 實例化本地HTML對象:
- etree .parse(filepath) # filepath為本地文件路徑
- 實例化網絡HTML對象:
- etree.prase("html_text") # html_text 為從網絡上爬取的網頁源碼
xpath (xpath表達式):
層級定位:
4.解決中文亂碼
1、對整個響應頁面進行編碼
# 解決中文亂碼 方法一 對獲得的整個頁面進行編碼 page_text = requests.get(url=url, headers=headers).encode("utf-8").text
2、對部分亂碼進行編碼
# 方法二 對亂碼內容進行編碼 img_title = a.xpath("./img/@alt")[0] + ".jpg" img_title = img_title.encode("iso-8859-1").decode("gbk")
requests高級用法
Cookie 和 session
在爬蟲程序中,當你訪進行用戶登錄請求后,再訪問用戶相關的頁面時,會出現讓你再次登錄的提示。
原因是http是無狀態協議,它不會自動保存登錄用戶的相關信息,所以為了解決這個問題,我們就需要用到Cookie和session
由于Cookie的安全性較低,所以目前都是使用session來進行保存會話
Session的使用
1、 創建session對象
# 創建session對象 session = requests.Session()
2、使用session發起登錄請求
使用此方式登錄之后,用戶的相關信息就會自動存儲到headers中,后續訪問用戶相關頁面就不用再次登錄了
# 使用session發起POST請求 用戶登錄 response = session.post(url=url, headers=headers, data=data)
3、使用帶有Cookie的session發起其他請求
# 使用帶有Cookie的session對象發起get請求 preson_pagetext = session.get(url=person_url, headers=headers).text
代理IP
現在大部分網站為了防止網站資源被惡意占用都會設置反爬機制,比如:“ip訪問頻率限制”。
為了解決這個反爬機制,我們就需要進行反反爬策略,對于限制ip這種機制,我們可以使用“ 代理IP ”進行解決。
代理的作用:
- 突破自身IP訪問的限制
- 隱藏自身的真是IP
代理相關網站:
- 快代理
- 西祠代理
- www.goubanjia.com
代理IP的類型:
- http :適用于使用Http協議的網站
- https:適用于使用https的網站
代理IP的匿名度:
- 透 明: 服務端知道該次請求是代理,可以看到真實ip
- 匿 名:服務端知道使用了代理,但是看不到真實IP
- 高匿名:服務端不知道是否使用了代理,也不知道真實IP
如何使用?
示例:
import requests url = "https://www.baidu.com/s?wd=ip" headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36' } # 未使用代理 page_text = requests.get(url=url, headers=headers).text # 使用代理 page_text = requests.get(url=url, headers=headers, proxies={"https": "113.194.28.99:9999"}).text

浙公網安備 33010602011771號