1. 程式人生 > >爬蟲學習筆記第4章.解析庫的使用.1 使用XPath

爬蟲學習筆記第4章.解析庫的使用.1 使用XPath

XPath:全稱XML Path Language(XML路徑語言),一門用於XML 文件中查詢資訊的語言。XPath 用於在 XML 文件中通過元素和屬性進行導航。XPath同樣可以用於HTML的搜尋。

XPath 路徑表示式:XPath 使用路徑表示式來選取 XML 文件中的節點或者節點集。這些路徑表示式和我們在常規的電腦檔案系統中看到的表示式非常相似。

1 - 初始化:模組匯入與物件構建

  1. 模組匯入。 Python中需要匯入lxml庫中的etree模組來使用XPath,即Python中需要匯入lxml庫中的etree模組來使用XPath,
from lxml import etree
  1. 解析物件構建。 用兩種方式用於構建XPath解析物件。

若text變數是html文字字串,則可使用

html=etree.HTML(text)

若檔案test.html是html文字檔案,則可使用

html=etree.parse('test.html',etree.HTMLParser())

需要注意的是,這裡etree模組自動修正了html文字。

2 - XPath節點

XML文件或者HTML文件是被當做節點樹來對待的。 XPath中有七種屬性的節點:元素節點,屬性節點,文字節點,名稱空間節點,處理指令節點,註釋節點以及文件(根)節點。常用的是前三種。 以下是常用術語:

  1. 基本值/原子值(Atomic Value):無父或無子的節點。
  2. 專案(Item):基本值或節點。
  3. 父(Parent):每個元素或屬性的直接上級節點。
  4. 子(Children):每個元素的下級節點。數量可能是0,1或者多個。
  5. 同胞(Sibling):擁有相同父的節點。
  6. 祖先(Ancestor):某個節點的父,父的父,等等。
  7. 後代(Descendant):某個節點的子,子的子,等等。

4 - XPath選取

XPath的選取非常簡單,若html是XPath解析物件,path是路徑表示式字串(將會在以下講解),則使用方法是

result=html.xpath(path)

返回選取結果result將是一個列表。再次選取可使用Python列表方法。 如果選取到的是元素,其形式將是類似<Element li at 0x10a3992c8>; 如果是其他,每個列表元素將是一個字串。

3 - 常用路徑表示式

表示式 描述 例子 效果
nodename 選取此節點所有子節點 book 選取book節點的所有子節點
/ 從當前節點選取直接子節點 /li 當前節點的名叫li的子節點
// 從當前節點選取所有子孫節點 //a 當前節點所有名叫a的子節點
選取當前節點的父節點 li//… 當前li節點的父節點
@ 選取屬性 @class class屬性
* 萬用字元:可匹配任意節點 //* 選取所有節點

以下是用於示例的html文字:

<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-2"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
<li class="item-1 it" name=“sixth”><a href="link6.html">sixth item</a></li>
<li class="item-1 it" name=“seventh”><a href="link7.html">seventh item</a></li>
</ul>
</div>

以下是選取示例:

  • ‘//*’:所有節點(從檔案根節點下選取所有節點)
  • ‘//li/a’:所有li節點的所有直接a子節點
  • ‘//ul//a’:所有ul節點下的所有a子孫節點
  • ‘//li[@class=“item-1”]’:屬性匹配。所有class屬性為item-1的li節點(即第二個li節點,注意沒有第6個)。
  • ‘//a[@href=“link4.html”]/…/@class’:選取href屬性為link4.html的a節點後,選取其直接父節點(即第4個li節點),再選取其屬性(‘item-1’)
  • ‘//li[@class=“item-0”]/a/text()’:文字獲取。所有class屬性為item-0的li節點(第一個和第五個)的直接a節點的所有文字( [‘first item’,‘fifth item’] )
  • ‘/li[@class=“item-0”]//text()’:所有class屬性為item-0的li節點及其子孫節點的所有文字。
  • ‘//li[@class=“item-inactive”]/a/@href’:屬性獲取。所有class屬性為item-inactive的li節點下a節點的href屬性([‘link3.html’])。
  • ‘//li[contains(@class,“it”)]/a/text()’:屬性多值匹配。所有class屬性包含it的li節點(第6個)下直接a節點的文字。
  • ‘//li[contains(@class,“it”) and @name=“seventh”]/a/text()’:多屬性匹配。所有class屬性包含it且name屬性包含seventh的li節點(即第7個)下的a節點的文字。

4 - 按序選擇與節點軸選擇

示例為以下html文字。

<div>
<ul>
<li class="item-0"><a href="link1.html"><span>first item<span></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-2"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a></li>
<li class="item-1 it" name=“sixth”><a href="link6.html">sixth item</a></li>
<li class="item-1 it" name=“seventh”><a href="link7.html">seventh item</a></li>
</ul>
</div>
  • ‘//li[2]/a/text()’:第2個(注意與陣列不同)li節點的子節點a下的文字([‘second item’])
  • ‘//li[last()]’:last()函式。最後一個li節點(即第7個)。
  • ‘//li[last()-2]’:倒數第3個li節點(最後一個倒推2個)。
  • //li[position()<4]’:position()函式。位置小於3(即第一個,第二個和第三個)的li節點。
  • ‘//li[1]/ancestor:: *’:節點軸選擇之ancestor軸。選取第一li節點的所有祖先節點(將包括檔案根節點html節點,body節點,以及明面上的ul和div節點)。
  • ‘//li[1]/ancestor::div’:選取第一個li節點的div祖先節點。
  • ‘//li[7]/attribute:: *’:選取第7個li節點的所有屬性值([‘item-1’,‘it’])。
  • ‘//li[3]/child::a[@href=“link3.html”]’:第3個li節點的所有子節點中href屬性為link3.html的a節點。
  • ‘li[1]/descendant:: span’:第一個li節點的所有子孫節點中的span節點。
  • ‘li[5]/following:: *[2]’:第5個li節點的所有文字中後續節點(包括一切子孫節點)中的第二個。
  • ‘li[2]/following-sibling:: *’ :第2個li節點的所有後續同胞節點。

5 - 一些其他

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