參考原文: 點選打開連結
XPath即為XML路徑語言,它是一種用來确定XML(标準通用标記語言的子集)文檔中某部分位置的語言。XPath基于XML的樹狀結構,有不同類型的節點,包括元素節點,屬性節點和文本節點,提供在資料結構樹中找尋節點的能力。 [1] 起初 XPath 的提出的初衷是将其作為一個通用的、介于XPointer與XSLT間的文法模型。但是 XPath 很快的被開發者采用來當作小型查詢語言。
from lxml import etree
text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >first item</a></li>
<li class="item-1"><a href="link2.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >second item</a></li>
<pi class="item-inactive"><a href="link3.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >third item</a></pi>
<ci class="item-1"><a href="link4.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >fourth item</a></ci>
<ti class="item-0"><a href="link5.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >fifth item</a></ti>
</ul>
</div>
'''
html = etree.HTML(text)
result = etree.tostring(html)
print(result)
1 節點關系
1.1 父節點
每個元素以及屬性都有一個父節點
在上面的例子中:div是ul的父節點,ul是li的父節點
1.2 子節點
在上面的例子中:ul是div的子節點,li是ul的子節點
1.3同胞節點
在上面的例子中:li、pi、ci、ti是同胞節點
1.4先輩節點
在上面的例子中:div是ul、pi、li、a的先輩節點
1.5後代節點
在上面的例子中:ul、pi、li、a是div的後代
2 規則和表達式
表達式:
路徑表達式
3 LXML用法
3.1擷取所有li标簽
其中,這裡展現了 lxml 的一個非常實用的功能就是自動修正 html 代碼,大家應該注意到了,最後一個 li 标簽,其實我把尾标簽删掉了,是不閉合的。不過,lxml 因為繼承了 libxml2 的特性,具有自動修正 HTML 代碼的功能。
from lxml import etree
text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >first item</a></li>
<li class="item-1"><a href="link2.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >second item</a></li>
<li class="item-inactive"><a href="link3.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >third item</a></li>
<li class="item-1"><a href="link4.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >fourth item</a></li>
<li class="item-0"><a href="link5.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >fifth item</a>
</ul>
</div>
'''
html = etree.HTML(text)
result = etree.tostring(html)
print(result)
輸出:<html><body>
<div>
<ul>
<li class="item-0"><a href="link1.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >first item</a></li>
<li class="item-1"><a href="link2.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >second item</a></li>
<li class="item-inactive"><a href="link3.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >third item</a></li>
<li class="item-1"><a href="link4.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >fourth item</a></li>
<li class="item-0"><a href="link5.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" >fifth item</a></li>
</ul>
</div>
</body></html>
利用parse來解析讀取檔案,把上述代碼存為hello.html的檔案名
from lxml import etree
html = etree.parse('hello.html')
result = etree.tostring(html, pretty_print=True)
print(result)
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]))
<class 'lxml.etree._ElementTree'>
[<Element li at 0x13f66488>, <Element li at 0x13f66b48>, <Element li at 0x13f66108>, <Element li at 0x13effb08>, <Element li at 0x13eff188>]
5
<class 'list'>
<class 'lxml.etree._Element'>
從上面的代碼中可以看出:etree.parse的類型為<class 'lxml.etree._ElementTree'>
通過Xpath之後有5個包含li的标簽
3.2擷取 <li> 标簽的所有 class
esult = html.xpath('//li/@class')
print (esult)
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
3.3 擷取 <li> 标簽下 href 為 link1.html 的 <a> 标簽
html.xpath('//li/a[@href="link1.html" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" target="_blank" rel="external nofollow" ]')
Out[7]: [<Element a at 0xa8d6d48>]
3.4 擷取 <li> 标簽下 所有的 <a> 标簽
html.xpath('//li/a[@href]')
Out[9]:
[<Element a at 0xa8d6d48>,
<Element a at 0xa951308>,
<Element a at 0xa8d6688>,
<Element a at 0xa984848>,
<Element a at 0xa984788>]
html.xpath('//li/a')
Out[10]:
[<Element a at 0xa8d6d48>,
<Element a at 0xa951308>,
<Element a at 0xa8d6688>,
<Element a at 0xa984848>,
<Element a at 0xa984788>]
html.xpath('//li//a')
Out[11]:
[<Element a at 0xa8d6d48>,
<Element a at 0xa951308>,
<Element a at 0xa8d6688>,
<Element a at 0xa984848>,
<Element a at 0xa984788>]
3.5 擷取最後一個 <li> 的 <a> 的 href
html.xpath('//li[last()]/a/@href')
Out[16]: ['link5.html']
3.6 擷取倒數第二個 <li> 的 <a> 的 href
result = html.xpath('//li[last()-1]/a')
print (result[0].text)
3.7 擷取倒數第二個 <li> 的 <a> 的标簽
html.xpath('//li[last()-1]/a')[0].tag