Python 爬蟲利器三之 Xpath 語法與 lxml 庫的用法
前言
前面我們介紹了 BeautifulSoup 的用法,這個已經是非常強大的庫了,不過還有一些比較流行的解析庫,例如 lxml,使用的是 Xpath 語法,同樣是效率比較高的解析方法。如果大家對 BeautifulSoup 使用不太習慣的話,可以嘗試下 Xpath。
參考來源
lxml 用法源自 lxml python 官方文檔,更多內容請直接參閱官方文檔,本文對其進行翻譯與整理。 lxml XPath 語法參考 w3school w3school
視頻資源
如果你對 XPath 不熟悉的話,可以看下這個視頻資源: web 端功能自動化定位元素
安裝
1
pip install lxml
利用 pip 安裝即可
XPath 語法
XPath 是一門在 XML 文檔中查找信息的語言。XPath 可用來在 XML 文檔中對元素和屬性進行遍歷。XPath 是 W3C XSLT 標準的主要元素,并且 XQuery 和 XPointer 都構建于 XPath 表達之上。
節點關系
(1)父(Parent) 每個元素以及屬性都有一個父。 在下面的例子中,book 元素是 title、author、year 以及 price 元素的父:
1
2
3
4
5
6
(2)子(Children) 元素節點可有零個、一個或多個子。 在下面的例子中,title、author、year 以及 price 元素都是 book 元素的子:
1
2
3
4
5
6
(3)同胞(Sibling) 擁有相同的父的節點 在下面的例子中,title、author、year 以及 price 元素都是同胞:
1
2
3
4
5
6
(4)先輩(Ancestor) 某節點的父、父的父,等等。 在下面的例子中,title 元素的先輩是 book 元素和 bookstore 元素:
1
2
3
4
5
6
7
8
9
10
(5)后代(Descendant) 某個節點的子,子的子,等等。 在下面的例子中,bookstore 的后代是 book、title、author、year 以及 price 元素:
1
2
3
4
5
6
7
8
9
10
選取節點
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()<3]
選取最前面的兩個屬于 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
選取 book 元素的所有 title 和 price 元素。
//title | //price
選取文檔中的所有 title 和 price 元素。
/bookstore/book/title | //price
選取屬于 bookstore 元素的 book 元素的所有 title 元素,以及文檔中所有的 price 元素。
XPath 運算符
下面列出了可用在 XPath 表達式中的運算符:
運算符
描述
實例
返回值
|
計算兩個節點集
//book | //cd
返回所有擁有 book 和 cd 元素的節點集
+
加法
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
lxml 用法
初步使用
首先我們利用它來解析 HTML 代碼,先來一個小例子來感受一下它的基本用法。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
from lxml import etree
text = '''
'''
html = etree.HTML(text)
result = etree.tostring(html)
print(result)
首先我們使用 lxml 的 etree 庫,然后利用 etree.HTML 初始化,然后我們將其打印出來。 其中,這里體現了 lxml 的一個非常實用的功能就是自動修正 html 代碼,大家應該注意到了,最后一個 li 標簽,其實我把尾標簽刪掉了,是不閉合的。不過,lxml 因為繼承了 libxml2 的特性,具有自動修正 HTML 代碼的功能。 所以輸出結果是這樣的
1
2
3
4
5
6
7
8
9
10
11
12
不僅補全了 li 標簽,還添加了 body,html 標簽。
文件讀取
除了直接讀取字符串,還支持從文件讀取內容。比如我們新建一個文件叫做 hello.html,內容為
1
2
3
4
5
6
7
8
9
利用 parse 方法來讀取文件。
1
2
3
4
from lxml import etree
html = etree.parse('hello.html')
result = etree.tostring(html, pretty_print=True)
print(result)
同樣可以得到相同的結果。
XPath 實例測試
依然以上一段程序為例 (1)獲取所有的
標簽
1
2
3
4
5
6
7
8
from lxml import etree
html = etree.parse('hello.html')
print type(html)
result = html.xpath('//li')
print result
print len(result)
print type(result)
print type(result[0])
運行結果
1
2
3
4
5
[
5
可見,etree.parse 的類型是 ElementTree,通過調用 xpath 以后,得到了一個列表,包含了 5 個
元素,每個元素都是 Element 類型 (2)獲取
標簽的所有 class
1
2
result = html.xpath('//li/@class')
print result
運行結果
1
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
(3)獲取
標簽下 href 為 link1.html 的 標簽
1
2
result = html.xpath('//li/a[@href="link1.html"]')
print result
運行結果
1
[
(4)獲取
標簽下的所有 標簽 注意這么寫是不對的
1
result = html.xpath('//li/span')
1
result = html.xpath('//li/span')
因為 / 是用來獲取子元素的,而 并不是
的子元素,所以,要用雙斜杠
1
2
result = html.xpath('//li//span')
print result
運行結果
1
[
(5)獲取
標簽下的所有 class,不包括
1
2
result = html.xpath('//li/a//@class')
print result
運行結果
1
['blod']
(6)獲取最后一個
的 的 href
1
2
result = html.xpath('//li[last()]/a/@href')
print result
運行結果
1
['link5.html']
(7)獲取倒數第二個元素的內容
1
2
result = html.xpath('//li[last()-1]/a')
print result[0].text
運行結果
1
fourth item
(8)獲取 class 為 bold 的標簽名
1
2
result = html.xpath('//*[@class="bold"]')
print result[0].tag
運行結果
1
span
通過以上實例的練習,相信大家對 XPath 的基本用法有了基本的了解。也可以利用 text 方法來獲取元素的內容。 大家多加練習!
結語
XPath 是一個非常好用的解析方法,同時也作為爬蟲學習的基礎,在后面的 selenium 以及 scrapy 框架中都會涉及到這部分知識,希望大家可以把它的語法掌握清楚,為后面的深入研究做好鋪墊。
Python XML 彈性文件服務
版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。