1. 程式人生 > >我要爬爬蟲(7)-xpath解析庫

我要爬爬蟲(7)-xpath解析庫

常用符號

/ 直接子節點
// 所有子孫節點
. 當前節點
.. 當前節點的父節點
@ 屬性值
contains 屬性包括

lxml庫的使用

對於下面這段html文字source.html

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

直接解析html文字

from lxml import etree
#HTML方法傳入html文字構造xpath解析物件,並可自動修復預設格式
html=etree.HTML('XXXXXXXXXX')
#tostring轉換成bytes
result=etree.tostring(html)
#decode轉換成string
print(result.decode('gbk')) 
#解碼之後可以實現換行輸出,utf-8或gbk都行

結果如下

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

其實就是個補全格式的操作。

也可對html檔案進行解析。

html=etree.parse('source.html',parser=etree.HTMLParser())
result=etree.tostring(html)
print(result.decode('gbk'))
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body><div>&#13;
    <ul>&#13;
        <li class="item-0"><a href="link1.html">first time</a> </li>&#13;
        <li class="item-1"><a href="link2.html">second time</a> </li>&#13;
        <li class="item-inactive"><a href="link3.html">third time</a> </li>&#13;
        <li class="item-1"><a href="link4.html">fouth time</a> </li>&#13;
        <li class="item-0"><a href="link5.html">fifth time</a> </li>&#13;
    </ul>&#13;
</div></body></html>

多了個DOCTYPE的宣告,其他一樣。

取節點

html.xpath('//*')取得所有子孫節點
列表形式返回所有節點

[<Element html at 0x1626ad130c8>,
 <Element body at 0x1626ac5d648>,
 <Element div at 0x1626ad1c108>,
 <Element ul at 0x1626ad1cfc8>,
 <Element li at 0x1626ad1c788>,
 <Element a at 0x1626ad1c8c8>,
 <Element li at 0x1626ad1c648>,
 <Element a at 0x1626ad1c848>,
 <Element li at 0x1626ad1c388>,
 <Element a at 0x1626ad1c3c8>,
 <Element li at 0x1626ad1c208>,
 <Element a at 0x1626ad1c188>,
 <Element li at 0x1626ad1c6c8>,
 <Element a at 0x1626ad1c688>]

//li取得所有li節點
//li/a取得所有li節點下的直接a節點
//a[@href="link4.html"]/../@class取得所有滿足href=“link4.html”的a節點的父節點的class屬性
li[@class="item-0"]/text()這裡取不到任何值
結果[' ', '\n ']
因為li節點的直接子節點沒有文字,只有a節點和空格,以及構造xpath物件時新增的換行符。
對於<li class="li li-first"><a href="link.html"><a/><li/>
這裡li節點的class屬性有兩個值li li-first,所以用[@class='li']是取不到該節點的,應該使用[contains(@class,'li')],這樣屬性值裡包含即可匹配到。
//li[contains(@class,"li") and @name="item"]/a/text()這裡使用and並列查詢條件。
//li[1]下標1即取第一個節點,並非第二個
//li[last()]最後一個節點
//li[position()<3]下標小於3,即第一,第二個節點。
//li[last()-2]倒數第三個節點

節點軸

ancestor 祖先節點
attribute 屬性值
child 子節點
decedent 子孫節點
following 後面的節點
following-sibling 後面的同級節點
//li[1]/following::*2第一個li節點的後面第二個節點