1. 程式人生 > 其它 >Python解析庫lxml與xpath用法總結

Python解析庫lxml與xpath用法總結

本文主要圍繞以xpath和lxml庫進行展開:

一、xpath 概念、xpath節點、xpath語法、xpath軸、xpath運算子

二、lxml的安裝、lxml的使用、lxml案例

一、xpath

1.xpath概念

XPath 是一門在 XML 文件中查詢資訊的語言。XPath 使用路徑表示式在 XML 文件中進行導航 。XPath 包含一個標準函式庫 。XPath 是 XSLT 中的主要元素 。XPath 是一個 W3C 標準 。

2.xpath節點

xpath有七種型別的節點:元素、屬性、文字、名稱空間、處理指令、註釋以及文件(根)節點。

節點關係:父、子、兄弟、先輩、後輩。

3.xpath語法

xpath語法在W3c網站上有詳細的介紹,這裡擷取部分知識,供大家學習。

XPath 使用路徑表示式在 XML 文件中選取節點。節點是通過沿著路徑或者 step 來選取的。下面列出了最有用的路徑表示式:

表示式 描述
nodename 選取此節點的所有子節點。
/ 從根節點選取。
// 從匹配選擇的當前節點選擇文件中的節點,而不考慮它們的位置。
. 選取當前節點。
.. 選取當前節點的父節點。
@ 選取屬性。

在下面的表格中,我們已列出了一些路徑表示式以及表示式的結果:

路徑表示式 結果
bookstore 選取 bookstore 元素的所有子節點。
/bookstore 選取根元素 bookstore。註釋:假如路徑起始於正斜槓( / ),則此路徑始終代表到某元素的絕對路徑!
bookstore/book 選取屬於 bookstore 的子元素的所有 book 元素。
//book 選取所有 book 子元素,而不管它們在文件中的位置。
bookstore//book 選擇屬於 bookstore 元素的後代的所有 book 元素,而不管它們位於 bookstore 之下的什麼位置。
//@lang 選取名為 lang 的所有屬性。

謂語(Predicates)

謂語用來查詢某個特定的節點或者包含某個指定的值的節點。

謂語被嵌在方括號中。

在下面的表格中,我們列出了帶有謂語的一些路徑表示式,以及表示式的結果:

路徑表示式 結果
/bookstore/book[1] 選取屬於 bookstore 子元素的第一個 book 元素。
/bookstore/book[last()] 選取屬於 bookstore 子元素的最後一個 book 元素。
/bookstore/book[last()-1] 選取屬於 bookstore 子元素的倒數第二個 book 元素。
/bookstore/book[position()❤️] 選取最前面的兩個屬於 bookstore 元素的子元素的 book 元素。
//title[@lang] 選取所有擁有名為 lang 的屬性的 title 元素。
//title[@lang='eng'] 選取所有 title 元素,且這些元素擁有值為 eng 的 lang 屬性。
/bookstore/book[price>35.00] 選取 bookstore 元素的所有 book 元素,且其中的 price 元素的值須大於 35.00。
/bookstore/book[price>35.00]/title 選取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值須大於  35.00。

選取未知節點

XPath 萬用字元可用來選取未知的 XML 元素。

萬用字元 描述
* 匹配任何元素節點。
@* 匹配任何屬性節點。
node() 匹配任何型別的節點。

在下面的表格中,我們列出了一些路徑表示式,以及這些表示式的結果:

路徑表示式 結果
/bookstore/* 選取 bookstore 元素的所有子元素。
//* 選取文件中的所有元素。
//title[@*] 選取所有帶有屬性的 title 元素。

選取若干路徑

通過在路徑表示式中使用"|"運算子,您可以選取若干個路徑。

在下面的表格中,我們列出了一些路徑表示式,以及這些表示式的結果:

路徑表示式 結果
//book/title //book/price
//title //price
/bookstore/book/title //price

4.xpath 軸

軸可定義相對於當前節點的節點集。

軸名稱 結果
ancestor 選取當前節點的所有先輩(父、祖父等)。
ancestor-or-self 選取當前節點的所有先輩(父、祖父等)以及當前節點本身。
attribute 選取當前節點的所有屬性。
child 選取當前節點的所有子元素。
descendant 選取當前節點的所有後代元素(子、孫等)。
descendant-or-self 選取當前節點的所有後代元素(子、孫等)以及當前節點本身。
following 選取文件中當前節點的結束標籤之後的所有節點。
namespace 選取當前節點的所有名稱空間節點。
parent 選取當前節點的父節點。
preceding 選取文件中當前節點的開始標籤之前的所有節點。
preceding-sibling 選取當前節點之前的所有同級節點。
self 選取當前節點。

5.xpath運算子

下面列出了可用在 XPath 表示式中的運算子:

運算子 描述 例項 返回值
計算兩個節點集 //book
+ 加法 6 + 4 10
- 減法 6 - 4 2
* 乘法 6 * 4 24
div 除法 8 div 4 2
= 等於 price=9.80 如果 price 是 9.80,則返回 true。如果 price 是 9.90,則返回 false。
!= 不等於 price!=9.80 如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。
< 小於 price<9.80 如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。
<= 小於或等於 price<=9.80 如果 price 是 9.00,則返回 true。如果 price 是 9.90,則返回 false。
> 大於 price>9.80 如果 price 是 9.90,則返回 true。如果 price 是 9.80,則返回 false。
>= 大於或等於 price>=9.80 如果 price 是 9.90,則返回 true。如果 price 是 9.70,則返回 false。
or price=9.80 or price=9.70 如果 price 是 9.80,則返回 true。如果 price 是 9.50,則返回 false。
and price>9.00 and price<9.90 如果 price 是 9.80,則返回 true。如果 price 是 8.50,則返回 false。
mod 計算除法的餘數 5 mod 2 1

好了,xpath的內容就這麼多了。接下來我們要介紹一個神器lxml,他的速度很快,曾經一直是我使用beautifulsoup時最鍾愛的解析器,沒有之一,因為他的速度的確比其他的html.parser 和html5lib快了許多。

二、lxml

1.lxml安裝

lxml 是一個xpath格式解析模組,安裝很方便,直接pip install lxml 或者easy_install lxml即可。

2.lxml 使用

lxml提供了兩種解析網頁的方式,一種是你解析自己寫的離線網頁時,另一種 則是解析線上網頁。

匯入包:

from lxml import  etree

1.解析離線網頁:

html=etree.parse('xx.html',etree.HTMLParser())
aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/@href')
print(aa)

2.解析線上網頁:

from lxml import etree
import requests
rep=requests.get('https://www.baidu.com')
html=etree.HTML(rep.text)
aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/@href')
print(aa)

那麼我們怎麼獲取這些標籤和標籤對應的屬性值了,很簡單,首先獲取標籤只需你這樣做:


然後我們可以,比方說,你要獲取a標籤內的文字和它的屬性href所對應的值,有兩種方法,

1.表示式內獲取

aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/text()')

ab=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]/@href')

2.表示式外獲取

aa=html.xpath('//*[@id="s_xmancard_news"]/div/div[2]/div/div[1]/h2/a[1]')

aa.text

aa.attrib.get('href')

這樣就完成了獲取,怎麼樣,是不是很簡單了,哈哈哈。

下面再來lxml的解析規則:

表示式 描述
nodename 選取此節點的所有子節點
/ 從當前節點選取直接子節點
// 從當前節點選取子孫節點
. 選取當前節點
.. 選取當前節點的父節點
@ 選取屬性

html = lxml.etree.HTML(text)
#使用text構造一個XPath解析物件,etree模組可以自動修正HTML文字
html = lxml.etree.parse('./ex.html',etree.HTMLParser())
#直接讀取文字進行解析
from lxml import etree
result = html.xpath('//*')
#選取所有節點
result = html.xpath('//li')
#獲取所有li節點
result = html.xpath('//li/a')
#獲取所有li節點的直接a子節點
result = html.xpath('//li//a')
#獲取所有li節點的所有a子孫節點
result = html.xpath('//a[@href="link.html"]/../@class')
#獲取所有href屬性為link.html的a節點的父節點的class屬性
result = html.xpath('//li[@class="ni"]')
#獲取所有class屬性為ni的li節點
result = html.xpath('//li/text()')
#獲取所有li節點的文字
result = html.xpath('//li/a/@href')
#獲取所有li節點的a節點的href屬性
result = html.xpath('//li[contains(@class,"li")]/a/text())
#當li的class屬性有多個值時,需用contains函式完成匹配
result = html.xpath('//li[contains(@class,"li") and @name="item"]/a/text()')
#多屬性匹配
result = html.xpath('//li[1]/a/text()')
result = html.xpath('//li[last()]/a/text()')
result = html.xpath('//li[position()<3]/a/text()')
result = html.xpath('//li[last()-2]/a/text()')
#按序選擇,中括號內為XPath提供的函式
result = html.xpath('//li[1]/ancestor::*')
#獲取祖先節點
result = html.xpath('//li[1]/ancestor::div')
result = html.xpath('//li[1]/attribute::*')
#獲取屬性值
result = html.xpath('//li[1]/child::a[@href="link1.html"]')
#獲取直接子節點
result = html.xpath('//li[1]/descendant::span')
#獲取所有子孫節點
result = html.xpath('//li[1]/following::*[2]')
#獲取當前節點之後的所有節點的第二個
result = html.xpath('//li[1]/following-sibling::*')
#獲取後續所有同級節點

3.lxml案例

為了偷懶,小編決定還是採用urllib那篇文章的程式碼,哈哈哈,機智如我。

好了,今天就講這麼多,大家感興趣的話可以多多關注哦,精彩不停息!!!!