環境
Python 3.6.5
Pycharm Professional 2017.1
需要預備的知識
第二章內容
簡介
當你通過一些模擬請求手段,並且有幸突破了反爬,拿到了包含正確數據的請求結果,而且結果的格式是html,那麼就該xpath上場了。
xpath是一種路徑表達式,利用一定的規則在xml/html中查找信息。
lxml 是一個html/xml的解析器,主要的功能是解析和提取html/xml數據。lxml和正則一樣,也是用C實現的,是一款高性能的python html/xml解析器,可以利用xpath語法,來快速的定位特定元素以及節點信息。
lxml python 官方文檔:http://lxml.de/index.html
安裝
在pycharm的terminal終端命令窗口中輸入:
pip install lxml
或者使用清華源的鏡像,會更快一點
pip install -i https://pypi.tuna.tsinghua.edu.cn/simple lxml
知識
個人使用體驗,lxml這個工具,就是把html/xml處理爲類似dom的樹形結構,然後基於樹的層次結構(即xpath路徑表達式),迅速定位特定節點,然後從節點獲取屬性或者信息(這裏的節點指的就是html的一個個標籤)。
所以使用lxml分爲兩步:
- 使用lxml將html這個超大字符串進行初始化(固定不變的,而且這個字符串必須符合html的規範,這個需要注意,不然有些小夥伴有時候不關注返回結果類型,強行使用lxml與xpath)
- 使用xpath表達式,提取lxml構造的”dom“中的信息
第一步初始化
# 導入剛安裝好的輪子
from lxml import etree
# 加載Html字符串
root = etree.HTML(html)
#如果是文件 換成parse(path)
# root = etree.parse(path)
print(root)
print(type(root))
print(etree.tostring(root))
etree.HTML函數所需的字符串,就是之前requests獲取的結果,這樣串起來就是這樣的結構:
import requests
from lxml import etree
# 獲取應答對象
response = requests.get(url)
# 提取響應信息
html_str = response.content.decode()
# 對html字符串進行初始化
root = etree.HTML(html_str)
第二步xpath路徑表達式提取信息
我們拿一個簡單的html字符串進行
html_str = """
<html>
<head>
<title>xpath學習</title>
</head>
<body>
<ul>
<li id="l1">
<h3 class="title" href="https://www.huawei.com/cn/">華爲</h3>
<p class="price">5000</p>
</li>
<li id="l2">
<h3 class="title" href="https://www.mi.com/">小米</h3>
<p class="price">3000</p>
</li>
<li id="l3">
<h3 class="title">藍綠</h3>
<p class="price">4000</p>
</li>
</ul>
<div>
<li id="l4">
<h3 class="xxx">蘋果</h3>
<p class="price">10000</p>
</li>
</div>
<div>
<li id="l5">
<h3 class="xxx">諾基亞</h3>
<p class="price">2000</p>
</li>
</div>
</body>
</html>"""
選取節點
表達式 | 描述 |
---|---|
/ | 從當前節點尋找下一層節點 |
// | 從當前節點尋找所有節點,不考慮層級 |
. | 選取當前節點 |
… | 選取當前節點的父節點 |
@. | 選取節點屬性 |
text() | 選取節點的*innerHTML *文本 |
看到 ‘/’,‘//’,‘.’,‘…’ 這些符號不知道大家能想到什麼,對了那就是IO、文件。大家可以把xpath想象成我們在文件資源管理查找文件。文件資源管理器本身也是一個樹形結構,你可以使用C:\Users\LFF\Desktop\text.txt這種類似的路徑找到你想找的文件。
# 構建DOM
root = etree.HTML(html_str )
# 使用路徑表達式取數據
# . 取當前節點 如果只是單獨一個點的話訪問的爲根節點
result = root.xpath(".")
# / 取子節點
result = root.xpath("/html/head/title")
# // 不考慮位置 只要標籤名一致 全部取出
result = root.xpath("//h3")
# .. 返回當前標籤的上一級標籤
result = root.xpath("//p/..")
# @ 取標籤裏邊的屬性 (返回類型以及是etree._ElementUnicodeResult,上面的表達式最後一層不是@屬性或者text()的返回值都爲etree._Element)
result = root.xpath("//ul/li/h3/@href")
# text() 取標籤裏邊的innerHTML (屬於字符串信息 不屬於元素)
result = root.xpath("//h3/text()")
# 打印xpath結果信息
for item in result:
#
if type(item) == etree._ElementUnicodeResult:
print(item)
else:
print(etree.tostring(item))
帶條件的選擇節點
主要分爲兩種方式,一種是按節點的位置進行過濾,一種是按節點是否包含特定的屬性進行過濾
表達式 | 描述 |
---|---|
//h3[3] | 選取第三個h3標籤,類似索引,不過是從1開始 |
//h3[last()] | 取最後一個h3標籤,這裏不是用的-1 |
//h3[last()-1] | 取倒數第二個h3標籤,這裏按位置篩選,類似索引的寫法支持加減法 |
//h3[position() < 3] | 取位置小於3的h3標籤,即第一個和第二個h3標籤 |
//h3[@href] | 選取所有擁有href屬性的h3標籤 |
//h3[@class=“title”] | 選取所有擁有class屬性且class屬性爲title的h3標籤 |
root = etree.HTML(html_str)
# 按照位置進行過濾
result = root.xpath("//h3")
result = root.xpath("//h3[last()]")
result = root.xpath("//h3[last()-1]")
result = root.xpath("//h3[position()<3]")
# 按照屬性進行過濾
result = root.xpath("//h3[@href]")
result = root.xpath(" //h3[@class='title']")
# 取出text,查看xpath選取結果
for item in result:
# result獲取的符合條件的h3標籤,item此時指的就是h3標籤
# .表示的就是h3標籤,從h3標籤往下選擇裏邊的文本
print(item.xpath("./text()"))
其他選取方式
表達式 | 描述 |
---|---|
//li/* | 選取所有li下邊的子標籤 |
//h3 | //p | 同時選取所有h3標籤和p標籤 |
//節點名字[contains(@屬性名/text(),“子字符串”)] | 選取屬性包含某個字符串的標籤 |
starts-wiith(@屬性名/text(),"子字符串“) | 選取屬性以某個字符串開頭的標籤 |
xpath瀏覽器輔助分析插件
火狐:
頁面xpath測試插件:TryXpath
頁面xpath智能提示插件:TruePath
谷歌:
頁面xpath測試插件:ChroXpath
頁面xpath測試插件:Xpath Helper
但這些插件給出的xpath路徑表達式只供參考,一般情況下,需要修改才能在程序中使用。
任務
貼吧信息
http://tieba.baidu.com/f?ie=utf-8&kw=%E7%AC%94%E8%AE%B0%E6%9C%AC&fr=search&red_tag=b3364292370