天天看點

python爬蟲之Xpath和lxml學習筆記03

     參考原文: 點選打開連結

      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 規則和表達式

表達式:

python爬蟲之Xpath和lxml學習筆記03

路徑表達式

python爬蟲之Xpath和lxml學習筆記03
python爬蟲之Xpath和lxml學習筆記03
python爬蟲之Xpath和lxml學習筆記03
python爬蟲之Xpath和lxml學習筆記03
python爬蟲之Xpath和lxml學習筆記03

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