XPath解析 XPath(XML Path Language)是一種用于在XML和HTML文檔中查找信息的語(yǔ)言,其通過(guò)路徑表達(dá)式來(lái)定位節(jié)點(diǎn),屬性和文本內(nèi)容,并支持復(fù)雜查詢條件,XPath 是許多 Web 抓取工具如 Scrapy,Selenium 等的核心技術(shù)之一 XPath 解析的基本步驟 導(dǎo)入
XPath(XML Path Language)是一種用于在XML和HTML文檔中查找信息的語(yǔ)言,其通過(guò)路徑表達(dá)式來(lái)定位節(jié)點(diǎn),屬性和文本內(nèi)容,并支持復(fù)雜查詢條件,XPath 是許多 Web 抓取工具如
Scrapy,Selenium
等的核心技術(shù)之一
導(dǎo)入lxml.etree
from lxml import etree
使用etree.parse(filename, parser=None)函數(shù)返回一個(gè)樹形結(jié)構(gòu)
etree.parse()
用于解析本地XML或HTML文件,并將其轉(zhuǎn)換為一個(gè)樹形結(jié)構(gòu)即
ElementTree
對(duì)象,可以通過(guò)該對(duì)象訪問(wèn)文檔的各個(gè)節(jié)點(diǎn)
filename
:要解析的文件路徑
parser
(可選):默認(rèn)情況下,parser()會(huì)根據(jù)文件擴(kuò)展名自動(dòng)選擇合適的解析器,如
.xml
文件使用XML解析器,.html使用HTML解析器
使用etree.HTML(html_string, parser=None)解析網(wǎng)絡(luò)html字符串
html_string
:要解析的HTML字符串
parser
:(可選):默認(rèn)情況下
etree.HTML()
使用
etree.HTMLparser()
進(jìn)行解析
ELement
對(duì)象,表示HTML文檔的
根元素
,可以通過(guò)該對(duì)象訪問(wèn)文檔各個(gè)節(jié)點(diǎn)
使用.xpath(xpath_expression)在已經(jīng)解析好的HTML文檔中執(zhí)行XPath查詢
result = html_tree.xpath(xpath_expression)
xpath_expression
:XPath表達(dá)式,用于在文檔中查找節(jié)點(diǎn),XPath表達(dá)式可以是絕對(duì)路徑或相對(duì)路徑,也可以包含謂詞,函數(shù)和軸操作,主要的XPath語(yǔ)法下面會(huì)展開(kāi)講解
html_tree
:可以是
ElementTree
對(duì)象(由 etree.parse() 返回)或
Element
對(duì)象(由 etree.HTML() 返回)
from lxml import etree
# 使用etree.parser()解析文件路徑
parser = etree.HTMLParser(encoding='utf-8') # 以u(píng)tf8進(jìn)行編碼
tree = etree.parse('../Learning02/三國(guó)演義.html', parser=parser)
print(tree)
#output->
# 使用etree.HTML()解析本地文件或網(wǎng)絡(luò)動(dòng)態(tài)HTML
# 讀取文件 解析為字符串
file = open('../Learning02/三國(guó)演義.html', 'r', encoding='utf-8')
data = file.read()
root = etree.HTML(data)
print(root)
#整合
root = etree.HTML(open('../Learning02/三國(guó)演義.html', 'r', encoding='utf-8').read())
print(root)
#output->
XPath
語(yǔ)法可以用于在XML與HTML文檔中查找信息的語(yǔ)言
XPath使用路徑表達(dá)式來(lái)定位文檔中的節(jié)點(diǎn),路徑也可以分為絕對(duì)路徑與相對(duì)路徑
/
:表示從根節(jié)點(diǎn)開(kāi)始選擇,其用于定義一個(gè)絕對(duì)路徑
從根節(jié)點(diǎn)html開(kāi)始查找到head,再?gòu)膆ead下找出title標(biāo)簽
root = etree.HTML(open('../Learning02/三國(guó)演義.html', 'r', encoding='utf-8').read())
all_titles = root.xpath('/html/head/title')
for title in all_titles:
print(etree.tostring(title, encoding='utf-8').decode('utf-8'))
#output-> 《三國(guó)演義》全集在線閱讀_史書典籍_詩(shī)詞名句網(wǎng)
相比與絕對(duì)路徑,相對(duì)路徑使用率更好,更好用
//
:表示從
當(dāng)前節(jié)點(diǎn)開(kāi)始,
選擇文檔中
所有符合條件的節(jié)點(diǎn),
并且不考慮他們的位置
root = etree.HTML(open('../Learning02/三國(guó)演義.html', 'r', encoding='utf-8').read())
all_a = root.xpath('//a')
for a in all_a:
print(a.text)
#None
#首頁(yè)
#分類
#作者
#...
./
:表示當(dāng)前節(jié)點(diǎn),通常用于指明當(dāng)前節(jié)點(diǎn)本身,避免混淆
all_a = root.xpath('//a')
print(all_a[1].xpath('./text()')) #./表示當(dāng)前的a標(biāo)簽
#output-> ['首頁(yè)']
@
:用于選擇元素的屬性,而不是元素本身
# 使用 @ 選擇 標(biāo)簽的 href 屬性
all_hrefs = root.xpath('//a[@href]')
for hrefs in all_hrefs:
print(etree.tostring(hrefs, encoding='unicode'))
謂語(yǔ)是
xpath
中用于進(jìn)一步篩選節(jié)點(diǎn)的表達(dá)式,通常放在方括號(hào)[]
內(nèi),其可以基于節(jié)點(diǎn)的位置,屬性值,文本內(nèi)容或其他條件來(lái) 選擇特定的節(jié)點(diǎn),謂語(yǔ)可以嵌套使用,也可以與其他謂語(yǔ)組合使用
基本語(yǔ)法
//element[condition]
element
:要選擇的元素
condition
:謂語(yǔ)中的條件,用于進(jìn)一步篩選符合條件的元素
位置謂語(yǔ)用于根據(jù)節(jié)點(diǎn)在兄弟節(jié)點(diǎn)中的位置進(jìn)行選擇,可以使用
position()
或直接指定位置編號(hào)
獲取第一個(gè)
ul
標(biāo)簽中的第一個(gè)
li
標(biāo)簽
#//ul獲取的是所有ul,[0]選擇第一個(gè)
lis = root.xpath('//ul')[0].xpath('./li[1]')
for li in lis:
print(etree.tostring(li, encoding='unicode'))
#output-> - 首頁(yè)
使用
last()
獲取最后第一個(gè)節(jié)點(diǎn),和導(dǎo)數(shù)第二個(gè)節(jié)點(diǎn)
# 倒一個(gè)
last_li = root.xpath('//ul')[0].xpath('./li[last()]')
print(etree.tostring(last_li[0], encoding='unicode'))
# 倒二個(gè)
last_second_li = root.xpath('//ul')[0].xpath('./li[last()-1]')
print(etree.tostring(last_second_li[0], encoding='unicode'))
#output-> - 安卓下載
#- 古籍
使用
position()
獲取位置進(jìn)行篩選
# 獲取前兩個(gè)li標(biāo)簽
last_li = root.xpath('//ul')[0].xpath('./li[position()<3]')
for li in last_li:
print(etree.tostring(li, encoding='unicode'))
# 獲取偶數(shù)位標(biāo)簽
lis = root.xpath('//ul')[0].xpath('./li[position() mod 2=0]')
for li in lis:
print(etree.tostring(li, encoding='unicode'))
屬性謂語(yǔ)
屬性謂語(yǔ)用于 選擇具體特定屬性的節(jié)點(diǎn)
@attribute
來(lái)獲取屬性名稱,結(jié)合條件進(jìn)行篩選
# 選取所有具有 href 屬性的 a 元素
hrefs = root.xpath("http://a[@href]")
for href in hrefs:
print(etree.tostring(href, encoding='unicode'))
class
屬性值
all_class = root.xpath('//@class')
print(all_class)
組合謂語(yǔ)
將多個(gè)條件組合在一起,使用邏輯運(yùn)算符
and,or
等來(lái)創(chuàng)建更復(fù)雜的謂語(yǔ)
#選取href屬性值為https://example.com且class屬性值為link的a元素
//a[@href='https://example.com' and @class='link']
#選取href屬性值為https://example.com或https://another.com的a 元素
//a[@href='https://example.com' or @href='https://another.com']
函數(shù)謂語(yǔ)
Xpath提供了許多內(nèi)置函數(shù),來(lái)應(yīng)對(duì)更復(fù)雜的篩選條件
contains((string1, string2)
函數(shù):
string1
:要搜索的字符串
string2
:要查找的字符串
# 選取class包含"book"的img標(biāo)簽
images = root.xpath('//img[contains(@src,"book")]')
for image in images:
print(etree.tostring(image, encoding='unicode'))
starts-with(string1, string2)
函數(shù):
檢查一個(gè)字符串是否以指定字符的前綴開(kāi)始,是返回
true
,否返回false
string1:
要檢查的字符串
string2:
作為前綴的字符串
# 選取所有href以https://開(kāi)頭的a標(biāo)簽
all_a = root.xpath('//a[starts-with(@href,"https:")]')
for a in all_a:
print(etree.tostring(a, encoding='unicode'))
文本內(nèi)容謂語(yǔ)
用于選擇包含特定文本內(nèi)容的節(jié)點(diǎn),可以使用
text()
函數(shù)來(lái)提取節(jié)點(diǎn)的文本內(nèi)容
# 選擇使用包含"三國(guó)"文本的p標(biāo)簽
paragraphs = root.xpath('//p[contains(text(),"三國(guó)")]')
for p in paragraphs:
print(etree.tostring(p, encoding='unicode'))
xpath提供了多種通配符,用于在路徑表達(dá)式中匹配未知的元素,屬性,或任何節(jié)點(diǎn).這些通配符非常有用,尤其是當(dāng)不確定具體節(jié)點(diǎn)名稱和結(jié)構(gòu)的情況下
通配符 | 描述 |
---|---|
* | 匹配任何元素節(jié)點(diǎn)。 一般用于瀏覽器copy xpath會(huì)出現(xiàn) |
@* | 匹配任何屬性節(jié)點(diǎn)。 |
node() | 匹配任何類型的節(jié)點(diǎn)。 |
*
匹配任何元素節(jié)點(diǎn)
*
是最常用的通配符之一,其可以匹配任何元素,而不需要具體標(biāo)簽名.這在不確定元素名稱或希望選擇所有類型的元素時(shí)非常有用
# 選擇所有 div 下的所有子元素
divs = root.xpath("http://div/*")
for div in divs:
print(etree.tostring(div, encoding='unicode'))
@*
匹配任何屬性節(jié)點(diǎn)
@*
用于匹配任何屬性節(jié)點(diǎn),而不用指定具體屬性名稱,在你不確定屬性名稱或希望選擇所有屬性時(shí)非常有用
# 選擇所有 a 元素的所有屬性
all_a = root.xpath('//a/@*')
for a in all_a:
print(a)
node()
匹配任何類型的節(jié)點(diǎn)
node()
是一個(gè)更通用的通配符,其能匹配任何類型節(jié)點(diǎn),包括元素節(jié)點(diǎn),文本節(jié)點(diǎn),屬性節(jié)點(diǎn),注釋節(jié)點(diǎn)等等,其在需要選擇不僅僅是元素節(jié)點(diǎn)是十分有用
# 選擇所有 ul 下的所有子節(jié)點(diǎn)(包括文本節(jié)點(diǎn))
nodes = root.xpath('//ul/node()')
print(nodes)
#output-> ['\n ', , '\n,...]
在之前的學(xué)習(xí)中我們首先學(xué)習(xí)了re正則表達(dá)式,其次學(xué)習(xí)了更加便捷的bs4,哪為何還要學(xué)習(xí)XPath解析呢,接下來(lái)我們將它們的優(yōu)點(diǎn)和適用場(chǎng)景進(jìn)行對(duì)比學(xué)習(xí)
工具 | 優(yōu)點(diǎn) | 缺點(diǎn) | 適用場(chǎng)景 |
---|---|---|---|
XPath
|
強(qiáng)大的路徑表達(dá)能力,支持層級(jí)結(jié)構(gòu)和條件查詢 | 學(xué)習(xí)曲線較陡,對(duì)不規(guī)范 HTML 容錯(cuò)性較差 | 結(jié)構(gòu)化良好的 XML/HTML,復(fù)雜查詢 |
re
|
靈活性高,適合處理純文本中的模式匹配 | 不適合解析 HTML/XML,可讀性差 | 從純文本中提取特定模式的數(shù)據(jù) |
BeautifulSoup
|
易于使用,容錯(cuò)性強(qiáng),適合初學(xué)者 | 性能稍低,功能有限 | 不規(guī)范的 HTML,簡(jiǎn)單數(shù)據(jù)提取,網(wǎng)頁(yè)抓取 |
機(jī)器學(xué)習(xí):神經(jīng)網(wǎng)絡(luò)構(gòu)建(下)
閱讀華為Mate品牌盛典:HarmonyOS NEXT加持下游戲性能得到充分釋放
閱讀實(shí)現(xiàn)對(duì)象集合與DataTable的相互轉(zhuǎn)換
閱讀鴻蒙NEXT元服務(wù):論如何免費(fèi)快速上架作品
閱讀算法與數(shù)據(jù)結(jié)構(gòu) 1 - 模擬
閱讀基于鴻蒙NEXT的血型遺傳計(jì)算器開(kāi)發(fā)案例
閱讀5. Spring Cloud OpenFeign 聲明式 WebService 客戶端的超詳細(xì)使用
閱讀Java代理模式:靜態(tài)代理和動(dòng)態(tài)代理的對(duì)比分析
閱讀Win11筆記本“自動(dòng)管理應(yīng)用的顏色”顯示規(guī)則
閱讀本站所有軟件,都由網(wǎng)友上傳,如有侵犯你的版權(quán),請(qǐng)發(fā)郵件[email protected]
湘ICP備2022002427號(hào)-10 湘公網(wǎng)安備:43070202000427號(hào)© 2013~2025 haote.com 好特網(wǎng)