xpath詳細講解

什麼是XML

  • XML 指可擴展標記語言(EXtensible Markup Language)
  • XML 是一種標記語言,很相似 HTML
  • XML 的設計宗旨是傳輸數據,而非顯示數據
  • XML 的標籤須要咱們自行定義。
  • XML 被設計爲具備自我描述性。
  • XML 是 W3C 的推薦標準

W3School官方文檔:http://www.w3school.com.cn/xml/index.asphtml

XML 和 HTML 的區別

數據格式node

描述python

設計目標web

XML工具

Extensible Markup Language (可擴展標記語言)性能

被設計爲傳輸和存儲數據,其焦點是數據的內容。學習

HTML開發工具

HyperText Markup Language (超文本標記語言)測試

顯示數據以及如何更好顯示數據。ui

HTML DOM

Document Object Model for HTML (文檔對象模型)

經過 HTML DOM,能夠訪問全部的 HTML 元素,連同它們所包含的文本和屬性。能夠對其中的內容進行修改和刪除,同時也能夠建立新的元素。

XML文檔示例
<?xml version="1.0" encoding="utf-8"?>
<bookstore>
 
<book category="cooking"> 
<title lang="en"></title>   Everyday Italian 
<author></author>    Giada De Laurentiis 
<year></year>    2005 
<price></price>    30.00
</book>  
 
<book category="children"> 
<title lang="en"></title>   Harry Potter 
<author></author>    J K. Rowling 
<year></year>    2005 
<price></price>    29.99
</book>  
 
<book category="web"> 
<title lang="en"></title>   XQuery Kick Start 
<author></author>    James McGovern 
<author></author>    Per Bothner 
<author></author>    Kurt Cagle 
<author></author>    James Linn 
<author></author>    Vaidyanathan Nagarajan 
<year></year>    2003 
<price></price>    49.99
</book> 
 
<book category="web" cover="paperback"> 
<title lang="en"></title>   Learning XML 
<author></author>    Erik T. Ray 
<year></year>    2003 
<price></price>    39.95
</book> 
</bookstore>
HTML DOM 模型示例

HTML DOM 定義了訪問和操做 HTML 文檔的標準方法,以樹結構方式表達 HTML 文檔。

 


XML的節點關係

1. 父(Parent)

每一個元素以及屬性都有一個父。

下面是一個簡單的XML例子中,book 元素是 title、author、year 以及 price 元素的父:

<?xml version="1.0" encoding="utf-8"?>
<book>
<title></title> Harry Potter
<author></author> J K. Rowling
<year></year> 2005
<price></price></book> 29.99

2. 子(Children)

元素節點可有零個、一個或多個子。

在下面的例子中,title、author、year 以及 price 元素都是 book 元素的子:

<?xml version="1.0" encoding="utf-8"?>
<book>
<title></title> Harry Potter
<author></author> J K. Rowling
<year></year> 2005
<price></price></book> 29.99

3. 同胞(Sibling)

擁有相同的父的節點

在下面的例子中,title、author、year 以及 price 元素都是同胞:

<?xml version="1.0" encoding="utf-8"?>
<book>
<title></title> Harry Potter
<author></author> J K. Rowling
<year></year> 2005
<price></price></book> 29.99

4. 先輩(Ancestor)

某節點的父、父的父,等等。

在下面的例子中,title 元素的先輩是 book 元素和 bookstore 元素:

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book>
<title></title> Harry Potter
<author></author> J K. Rowling
<year></year> 2005
<price></price></book> 29.99
</bookstore>

5. 後代(Descendant)

某個節點的子,子的子,等等。

在下面的例子中,bookstore 的後代是 book、title、author、year 以及 price 元素:

<?xml version="1.0" encoding="utf-8"?>
<bookstore>
<book>
<title></title> Harry Potter
<author></author> J K. Rowling
<year></year> 2005
<price></price></book> 29.99
</bookstore>

什麼是XPath?

XPath (XML Path Language) 是一門在 XML 文檔中查找信息的語言,可用來在 XML 文檔中對元素和屬性進行遍歷。

W3School官方文檔:http://www.w3school.com.cn/xpath/index.asp

XPath 開發工具

  1. 開源的XPath表達式編輯工具:XMLQuire(XML格式文件可用)
  2. Chrome插件 XPath Helper
  3. Firefox插件 XPath Checker

選取節點

XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。這些路徑表達式和咱們在常規的電腦文件系統中看到的表達式很是類似。

下面列出了最經常使用的路徑表達式:

表達式

描述

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。

                /a[contains(@href,'NameOnly')]表示選取href中包含NameOnly的a元素

   

 

 

選取未知節點

XPath 通配符可用來選取未知的 XML 元素。

通配符

描述

*

匹配任何元素節點。

@*

匹配任何屬性節點。

node()

匹配任何類型的節點。

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

路徑表達式

結果

/bookstore/*

選取 bookstore 元素的全部子元素。

//*

選取文檔中的全部元素。

html/node()/meta/@*

選擇html下面任意節點下的meta節點的全部屬性

//title[@*]

選取全部帶有屬性的 title 元素。

選取若干路徑

經過在路徑表達式中使用「|」運算符,您能夠選取若干個路徑。

實例

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

路徑表達式

結果

//book/title | //book/price

選取 book 元素的全部 title 和 price 元素。

//title | //price

選取文檔中的全部 title 和 price 元素。

/bookstore/book/title | //price

選取屬於 bookstore 元素的 book 元素的全部 title 元素,以及文檔中全部的 price 元素。

XPath的運算符

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

 

這些就是XPath的語法內容,在運用到Python抓取時要先轉換爲xml。

lxml庫

lxml 是 一個HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 數據。

lxml和正則同樣,也是用 C 實現的,是一款高性能的 Python HTML/XML 解析器,咱們能夠利用以前學習的XPath語法,來快速的定位特定元素以及節點信息。

lxml python 官方文檔:http://lxml.de/index.html

須要安裝C語言庫,可以使用 pip 安裝:pip install lxml (或經過wheel方式安裝)

初步使用

咱們利用它來解析 HTML 代碼,簡單示例:

# lxml_test.py
# 使用 lxml 的 etree 庫fromimportlxmletree
 
'''text =
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>
         <li class="item-1"><a href="link2.html">second item</a></li>
         <li class="item-inactive"><a href="link3.html">third item</a></li>
         <li class="item-1"><a href="link4.html">fourth item</a></li>
         <li class="item-0"><a href="link5.html">fifth item</a> # 注意,此處缺乏一個 </li> 閉合標籤
     </ul>
 </div>
'''
#利用etree.HTML,將字符串解析爲HTML文檔
html = etree.HTML(text)
# 按字符串序列化HTML文檔
result = etree.tostring(html)
 
print(result)

輸出結果:

<html><body><div>
<ul>   
<li class="item-0"><a href="link1.html"></a></li>        first item
<li class="item-1"><a href="link2.html"></a></li>        second item
<li class="item-inactive"><a href="link3.html"></a></li>        third item
<li class="item-1"><a href="link4.html"></a></li>        fourth item
<li class="item-0"><a href="link5.html"></a></li></ul>        fifth item
</div></body></html>

lxml 能夠自動修正 html 代碼,例子裏不只補全了 li 標籤,還添加了 body,html 標籤。

文件讀取:

除了直接讀取字符串,lxml還支持從文件裏讀取內容。咱們新建一個hello.html文件:

<!-- hello.html -->
<div>
<ul>   
<li class="item-0"><a href="link1.html"></a></li>        first item
<li class="item-1"><a href="link2.html"></a></li>        second item
<li class="item-inactive"><a href="link3.html"><span class="bold"></span></a></li>        third item
<li class="item-1"><a href="link4.html"></a></li>        fourth item
<li class="item-0"><a href="link5.html"></a></li>        fifth item
</ul>    
</div>

再利用 etree.parse() 方法來讀取文件。

# lxml_parse.py
fromimportlxmletree
# 讀取外部文件 hello.html
'./hello.html'html = etree.parse()
Trueresult = etree.tostring(html, pretty_print=)
 
print(result)

輸出結果與以前相同:

<html><body><div>
<ul>   
<li class="item-0"><a href="link1.html"></a></li>        first item
<li class="item-1"><a href="link2.html"></a></li>        second item
<li class="item-inactive"><a href="link3.html"></a></li>        third item
<li class="item-1"><a href="link4.html"></a></li>        fourth item
<li class="item-0"><a href="link5.html"></a></li></ul>        fifth item
</div></body></html>

XPath實例測試

1. 獲取全部的 <li> 標籤

# xpath_li.py
fromimportlxmletree
 
'hello.html'print# 顯示etree.parse() 返回類型html = etree.parse()type(html) 
 
'//li'result = html.xpath()
print# 打印<li>標籤的元素集合printprintprint0result len(result)type(result)type(result[])

輸出結果:

'lxml.etree._ElementTree'<type>
0x1014e0e180x1014e0ef00x1014e0f380x1014e0f800x1014e0fc85[<Element li at>, <Element li at>, <Element li at>, <Element li at>, <Element li at>]
'list'<type>
'lxml.etree._Element'<type>

2. 繼續獲取<li> 標籤的全部 class屬性

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
'//li/@class'result = html.xpath()
printresult

運行結果

['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']

3. 繼續獲取<li>標籤下hre 爲 link1.html 的 <a> 標籤

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
'//li/a[@href="link1.html"]'result = html.xpath()
printresult

運行結果

[<Element a at 0x10ffaae18>]

4. 獲取<li> 標籤下的全部 <span> 標籤

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
#result = html.xpath('//li/span')#注意這麼寫是不對的:#由於 / 是用來獲取子元素的,而 <span> 並非 <li> 的子元素,因此,要用雙斜槓
 
'//li//span'result = html.xpath()
printresult

運行結果

[<Element span at 0x10d698e18>]

5. 獲取 <li> 標籤下的<a>標籤裏的全部 class

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
'//li/a//@class'result = html.xpath()
printresult

運行結果

['blod']

6. 獲取最後一個 <li> 的 <a> 的 href

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
 
'//li[last()]/a/@href'# 謂語 [last()] 能夠找到最後一個元素result = html.xpath()
printresult

運行結果

['link5.html']

7. 獲取倒數第二個元素的內容

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
'//li[last()-1]/a'result = html.xpath()
# text 方法能夠獲取元素內容print0result[].text

運行結果

fourth item

8. 獲取 class 值爲 bold 的標籤名

# xpath_li.py
fromimportlxmletree
 
'hello.html'html = etree.parse()
 
'//*[@class="bold"]'result = html.xpath()
# tag方法能夠獲取標籤名print0result[].tag

運行結果

span
相關文章
相關標籤/搜索