【網路爬蟲的三種解析方式】
阿新 • • 發佈:2019-01-13
三種解析方式
- 正則解析
- Xpath解析
- BeautifulSoup解析
本文將詳細為大家講解三種聚焦爬蟲中的資料解析方式。
requests模組可實現資料爬取的流程
- 指定url
- 基於requests模組發起請求
- 獲取響應物件中的資料
- 進行持久化儲存
其實,在上述流程中還需要較為重要的一步,就是在持久化儲存之前需要進行指定資料解析。因為,在大多數情況下,我們都是指定去使用聚焦爬蟲,也就是爬取頁面中指定部分的資料值,而不是整個頁面的資料。因此,本文將詳細為大家講解三種聚焦爬蟲中的資料解析方式。至此,我們的資料爬取流程可以修改為:
- 指定url
- 基於requests模組發起請求
- 獲取響應中的資料
資料解析
- 進行持久化儲存
正則解析
注:這裡將從Python語言的視角講解
re.I
忽略大小寫
re.M
多行匹配
re.S
單行匹配
.*
貪婪模式
.*?
非貪婪(惰性)模式
?
0次或1次
+
1次或多次
*
0次或1次或多次
{m}
固定m次
{m, }
至少m次
{m, n}
m-n次
(\d?)
分組
(?P<name>\d?)
分組命名
(?P=name)
引用前面定義的命名分組
(?:\d?)
取消分組優先
(\d?)\1\1
通過預設分組編號向後引用(這裡將匹配3個相同的數字)
(?<=pattern)
向後肯定斷言的語法
關於正則的更多介紹,可見此文獻:【正則表示式介紹篇】
Xpath解析
pip install lxml
示例
我們先準備好用於測試的HTML頁面:<html lang="en"> <head> <meta charset="UTF-8" /> <title>Xpath解析測試</title> </head> <body
> <div> <p>百里守約</p> </div> <div class="song"> <p>李清照</p> <p>王安石</p> <p>蘇軾</p> <p>柳宗元</p> <a href="http://www.song.com/" title="趙匡胤" target="_self"> <span>this is span</span> 宋朝是最強大的王朝,不是軍隊的強大,而是經濟很強大,國民都很有錢</a> <a href="" class="du">總為浮雲能蔽日,長安不見使人愁</a> <img src="http://www.baidu.com/meinv.jpg" alt="" /> </div> <div class="tang"> <ul> <li><a href="http://www.baidu.com" title="qing">清明時節雨紛紛,路上行人慾斷魂,借問酒家何處有,牧童遙指杏花村</a></li> <li><a href="http://www.163.com" title="qin">秦時明月漢時關,萬里長征人未還,但使龍城飛將在,不教胡馬度陰山</a></li> <li><a href="http://www.126.com" alt="qi">岐王宅裡尋常見,崔九堂前幾度聞,正是江南好風景,落花時節又逢君</a></li> <li><a href="http://www.sina.com" class="du">杜甫</a></li> <li><a href="http://www.dudu.com" class="du">杜牧</a></li> <li><b>杜小月</b></li> <li><i>度蜜月</i></li> <li><a href="http://www.haha.com" id="feng">鳳凰臺上鳳凰遊,鳳去臺空江自流,吳宮花草埋幽徑,晉代衣冠成古丘</a></li> </ul> </div> </body> </html>開始測試:
from lxml import etree # pip install lxml # 本地檔案 tree = etree.parse('test01.html') # 如果是網路檔案,應使用etree.HTML() # 1.取出class為song的div標籤下的所有文字內容 ret01 = tree.xpath('//div[@class="song"]//text()') # //text() 表示取出某個標籤下文字內容和所有子標籤下的文字內容,如果存在文字,則返回的是單個元素的列表 # 2.取出class為tang的div下的直系子標籤ul下的直系子標籤第二個li下的直系子標籤a標籤下的內容 ret02 = tree.xpath('//div[@class="tang"]/ul/li[2]/a/text()') # /text() 表示取出某個標籤下的文字內容,如果存在文字,則返回的是單個或多個元素的文字 # li[2] 表示取第2個li標籤 # 3.取出href屬性值為空 且 class屬性值為du的a標籤內的文字內容 ret03 = tree.xpath('//a[@href="" and @class="du"]/text()') # 邏輯運算:and # 4.取出class包含 ta 的div標籤下的所有文字內容(包括子孫標籤) ret04 = tree.xpath('//div[contains(@class, "ta")]//text()') ret05 = tree.xpath('//div[starts-with(@class, "ta")]//text()') # 模糊匹配:contains(@class, "ta") 或 starts-with(@class, "ta") # 5.取出class為tang的div標籤下的任意標籤下li標籤(第2個)下的a標籤內href屬性的值 ret06 = tree.xpath('//div[@class="tang"]//li[2]/a/@href') # 6. / 開頭的,表示最外層的標籤 ret07 = tree.xpath('/html/body/div[@class="tang"]//text()') # 定位所有class為tang的div tree.xpath('//div[@class="tang"]') # 7. .// 表示從當前標籤開始找 ret08 = tree.xpath('.//a/text()') > # 8. | 表示或者 ret08 = tree.xpath('//div[@class="song"] | //div[@class="tang"]')
你還可以在瀏覽器中安裝xpaht外掛,以實現在瀏覽器中對xpath表示式進行驗證,以及通過html元素獲得xpath表示式。
例項:下載煎蛋網中的圖片
import os import base64 import requests from lxml import etree import urllib.request # 使用其來快速儲存內容 from fake_useragent import UserAgent # 隨機UA url = 'http://jandan.net/pic/page-%s#comments' # 煎蛋網 headers = { 'User-Agent': UserAgent(use_cache_server=False).random } page_text = requests.get(url=url % 1, headers=headers) # 爬取第1頁的內容 page_text.encoding = 'utf-8' content = page_text.text # 檢視頁面原始碼:發現所有圖片的src值都是一樣的。 # 簡單觀察會發現每張圖片載入都是通過jandan_load_img(this)這個js函式實現的。 # 在該函式後面還有一個class值為img-hash的標籤,裡面儲存的是一組hash值,該值就是加密後的img地址 # 加密就是通過js函式實現的,所以分析js函式,獲知加密方式,然後進行解密。 # 通過抓包工具抓取起始url的資料包,在資料包中全域性搜尋js函式名(jandan_load_img),然後分析該函式實現加密的方式。 # 在該js函式中發現有一個方法呼叫,該方法就是加密方式,對該方法進行搜尋 # 搜尋到的方法中會發現base64和md5等字樣,md5是不可逆的所以優先考慮使用base64解密 tree = etree.HTML(content) # 獲取所有加密的圖片地址 img_code_list = tree.xpath('//span[@class="img-hash"]/text()') # 開始解密 img_url_list = [] for code_url in img_code_list: img_url = 'http:' + base64.b64decode(code_url).decode() img_url_list.append(img_url) # 儲存圖片 dirname = '煎蛋圖' os.mkdir(dirname) for url in img_url_list: file_name = url.split('/')[-1] file_path = os.path.join(dirname, file_name) urllib.request.urlretrieve(url=url, filename=file_path) print(f'{file_path}已儲存')
BeautifulSoup解析
待