Python爬蟲網(wǎng)頁內(nèi)容提取工具xpath-創(chuàng)新互聯(lián)

上一節(jié),我們詳述了lxml.html的各種操作,接下來我們熟練掌握一下XPath,就可以熟練的提取網(wǎng)頁內(nèi)容了。

創(chuàng)新互聯(lián)公司專注于龍湖企業(yè)網(wǎng)站建設(shè),自適應(yīng)網(wǎng)站建設(shè),商城建設(shè)。龍湖網(wǎng)站建設(shè)公司,為龍湖等地區(qū)提供建站服務(wù)。全流程定制網(wǎng)站建設(shè),專業(yè)設(shè)計,全程項(xiàng)目跟蹤,創(chuàng)新互聯(lián)公司專業(yè)和態(tài)度為您提供的服務(wù)

XPath 是什么?

XPath的全稱是 XML Path Language,即XML 路徑語言,是一種在XML(HTML)文檔中查找信息的語言。它有4點(diǎn)特性:

  • XPath 使用路徑表達(dá)式在 XML 文檔中進(jìn)行導(dǎo)航
  • XPath 包含一個標(biāo)準(zhǔn)函數(shù)庫
  • XPath 是 XSLT 中的主要元素
  • XPath 是一個 W3C 標(biāo)準(zhǔn)

Python 爬蟲網(wǎng)頁內(nèi)容提取工具xpath

我們從網(wǎng)頁中提取數(shù)據(jù),主要應(yīng)用前兩點(diǎn)。

XPath 路徑表達(dá)式

使用XPath我們可以很容易定位到網(wǎng)頁中的節(jié)點(diǎn),也就是找到我們關(guān)心的數(shù)據(jù)。這些路徑跟電腦目錄、網(wǎng)址的路徑很相似,通過 / 來表示路徑的深度。

XPath 標(biāo)注函數(shù)庫

頭內(nèi)建了100多個函數(shù),當(dāng)然我們提取數(shù)據(jù)用到的有限,也就不用記住全部100多個函數(shù)了。

Xpath 的節(jié)點(diǎn)(Node)

XPath中的核心就是節(jié)點(diǎn)(Node),定義了7種不同類型的節(jié)點(diǎn): 元素(Element)、屬性(Attribute)、文本(Text)、命名空間(Namespace)、處理指令(processing-instruction)、注釋(Comment)和文檔節(jié)點(diǎn)(Document nodes)
這些節(jié)點(diǎn)組成一棵節(jié)點(diǎn)樹,樹的根節(jié)點(diǎn)被稱為文檔節(jié)點(diǎn)。
其中注釋就是html里面的注釋:``
而命名空間、處理指令和網(wǎng)頁數(shù)據(jù)提取基本沒關(guān)系,這里就不再詳述。

下面我們以一個簡單的html文檔為例,來解釋不同的節(jié)點(diǎn)及其關(guān)系。

<html> <body>     <div>ABC</div>     <ul id="menu">         <li>home</li>         <li>python</li>     </ul> </body> </html>

這段html中的節(jié)點(diǎn)有:

  • 文檔節(jié)點(diǎn):  <html>
  • 元素節(jié)點(diǎn): <li>python</li>
  • 屬性節(jié)點(diǎn):  id="menu"

XPath 節(jié)點(diǎn)的關(guān)系

節(jié)點(diǎn)間的關(guān)系完全照搬人類傳宗接代的輩分關(guān)系,但只是直系關(guān)系,沒有叔叔、大伯之類的旁系關(guān)系。
還是以上面的html文檔為例來說明節(jié)點(diǎn)關(guān)系:

父(Parent)

每個元素節(jié)點(diǎn)(Element)及其屬性都有一個父節(jié)點(diǎn)。
比如,body的父是html,而body是div、ul 的父親。

子(Children)

每個元素節(jié)點(diǎn)可以有零個、一個或多個子。
比如,body有兩個子:div,ul,而ul也有兩個子:兩個li。

同輩(Sibling)

同輩有相同的父輩節(jié)點(diǎn)。
比如,div和ul是同輩。

先輩(Ancestor)

某節(jié)點(diǎn)的父輩及其以上輩分的節(jié)點(diǎn)。
比如,li的父輩有:ul、div、body、html

后代(Descendant)

某節(jié)點(diǎn)的子及其子孫節(jié)點(diǎn)。
比如,body的后代有:div、ul、li。

XPath節(jié)點(diǎn)的選取

選取節(jié)點(diǎn),也就是通過路徑表達(dá)來實(shí)現(xiàn)。這是我們在網(wǎng)頁提取數(shù)據(jù)時的關(guān)鍵, 要熟練掌握 。

下表是比較有用的路徑表達(dá)式:

表達(dá)式 說明
nodename 選取當(dāng)前節(jié)點(diǎn)的名為nodename的所有子節(jié)點(diǎn)。
/ 從根節(jié)點(diǎn)選取,在路徑中間時表示一級路徑
// 從當(dāng)前節(jié)點(diǎn)開始選擇文檔中的節(jié)點(diǎn),可以是多級路徑
. 從當(dāng)前節(jié)點(diǎn)開始選取
.. 從父節(jié)點(diǎn)開始選取
@ 按屬性選取

接下來通過具體的示例來加深對路徑表達(dá)的理解:

路徑表達(dá)式 解釋
/html/body/ul/li 從根節(jié)點(diǎn)開始依照路徑選取li元素。返回多個。
//ul/li[1] 還是選取li元素,但是路徑多級跳躍到ul/li。[1]表示只取第一個li。
//li[last()] 還是選取li,但路徑更跳躍。[last()]表示取最后一個li元素。
//li[@class] 選取根節(jié)點(diǎn)的名為li且有class屬性的所有后代。
//li[@class=”item”] 選擇根節(jié)點(diǎn)的名為li且class屬性為item的所有后代。
//body/*/li 選取body的名為li的孫子節(jié)點(diǎn)。 * 是通配符,表示任何節(jié)點(diǎn)。
//li[@*] 選取所有帶屬性的li元素。
//body/div ` ` //body/ul 選取body的所有div和ul元素。
body/div 相對路徑,選取當(dāng)前節(jié)點(diǎn)的body元素的子元素div。絕對路徑以 / 開始。

XPath函數(shù)

Xpath的函數(shù)很多,涉及到錯誤、數(shù)值、字符串、時間等等,然而我們從網(wǎng)頁中提取數(shù)據(jù)的時候只會用到很少的一部分。其中最重要的就是字符串相關(guān)的函數(shù),比如contains()函數(shù)。

contains(a, b)

如果字符串a(chǎn)包含字符串b,則返回true,否則返回false。
比如: contains(‘猿人學(xué)Python’, ‘Python’),返回true
那么它用在什么時候呢?我們知道,一個html標(biāo)簽的class是可以有多個屬性值的,比如:

<div class="post-item text-red text-center">     ... </div>

這段html中div有三個class值,第一個表面它是一條發(fā)布的消息,后面兩個是對格式做了更多的設(shè)置。如果我們想提取網(wǎng)頁中所有發(fā)布的消息,只需要匹配到 post-item  即可,這時候就可以用上contains了:

doc.xpath('//div[contains(@class, "post-item")]')

跟contains()類似的字符串匹配的函數(shù)還有:

  • starts-with(string1, string2) 判斷string1是否以string2開頭
  • ends-with(string1, string2) 判斷string1是否以string2結(jié)尾
  • matches(string, pattern) 通過正則表達(dá)式匹配

然而,在lxml的xpath中使用ends-with(), matches() 會報錯

In [232]: doc.xpath('//ul[ends-with(@id, "u")]') --------------------------------------------------------------------------- XPathEvalError                            Traceback (most recent call last) <ipython-input-232-79a4afc46a75> in <module>() ----> 1 doc.xpath('//ul[ends-with(@id, "u")]') src/lxml/etree.pyx in lxml.etree._Element.xpath() src/lxml/xpath.pxi in lxml.etree.XPathElementEvaluator.__call__() src/lxml/xpath.pxi in lxml.etree._XPathEvaluatorBase._handle_result() XPathEvalError: Unregistered function

lxml 竟然不支持ends-with(), matches()函數(shù)
到lxml官方網(wǎng)站去看看,原來它說了只支持 XPath 1.0:

lxml supports XPath 1.0, XSLT 1.0 and the EXSLT extensions through libxml2 and libxslt in a standards compliant way.

接著又在Wikipedia上找到Xpath 2.0 和 1.0 的差異對比,果然ends-with(), matches() 只屬于2.0。下圖中,粗體部分是1.0包含的,其它是2.0也有的:

Python 爬蟲網(wǎng)頁內(nèi)容提取工具xpath
XPath 2.0 和 1.0 的差異

好了,Xpath在網(wǎng)頁內(nèi)容提取中要用到的部分已經(jīng)講完了

標(biāo)題名稱:Python爬蟲網(wǎng)頁內(nèi)容提取工具xpath-創(chuàng)新互聯(lián)
路徑分享:http://muchs.cn/article42/dhspec.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供響應(yīng)式網(wǎng)站、動態(tài)網(wǎng)站關(guān)鍵詞優(yōu)化、微信公眾號網(wǎng)站策劃、外貿(mào)網(wǎng)站建設(shè)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)

手機(jī)網(wǎng)站建設(shè)