寫這篇文章的原因是在極客學院一個關於Xpath教程中發現了幾處關鍵概念的錯誤.

上圖為視頻截圖, 有幾處錯誤, 一一說明.

最根本的錯誤, "/"不表示任何向下查詢, 這只是一個分割符號

Syntactically, a location path consists of one or more location steps, each separated by a forward slash (/):

locationstep/locationstep/locationstep

可以看出"/"僅僅是用於分割locationstep, 並沒有特殊含義. 但是當"/"位於開頭時, 也就是我們常說的絕對路徑, 表示根目錄, 與我們文件系統中"/"含義一樣:

An absolute location path starts from the root

element:/locationstep/locationstep/locationstep

但是大部分人認為的"/"表示子節點, 並且在使用過程中幾乎完全正確, 這又是怎麼回事?

其實我們把locationstep全部展開來看:

In an unabbreviated location path, a location step has the following syntax:

axis::node-test[predicate]

我們常見的是這一部分

node-test[predicate]

而我們很少關注的是

axis::

這表示的每一個locationstep的關係, 我們認為的向下查找就是其中的一個關係:

child::

選取當前節點(current context node)的子節點, 而在XPATH中, 這個節點是默認的, 也就是說, 除非你註明, 默認就是這個向下查找子節點.

現在我們知道為什麼大部分人理解錯誤, 但是基本可以正常使用的原因.

基於上面的認識, 那麼我們看看"//"的展開形式:

/descendant-or-self::node()

node() 表示選取任何類型的節點, 也就是全部節點

descendant-or-self:: 表示選取方向, 表示從當前節點向下選取所有後代節點以及自身

/ 位於開頭, 表示當前節點為文檔的root節點

連起來就是從root節點開始, 選取自身以及所有後代中的任意類型節點.

text()真會提取到你想要的文本嗎?

child::text() selects the text nodes that are children of the context node.

首先, 這隻會提取出當前節點子節點中的所有文位元組點, 並且以node-set的形式返回, 對應的也是Python中的list.

其實我們每一個locationstep的輸出結果都是node-set, 並且作為下一個locationstep的輸入數據.

locationstep/locationstep/locationstep

再看一次之前提到的形式, 用Python語言描述:每一個locationstep接受一個list作為參數, 經過

axis::node-test[predicate]

一系列處理之後, 輸出一個list.

那麼我們如何提取文本, 而不是一個list呢, 簡單點說, 使用XPATH中的文本函數, 比如string().

這裡不細說, 這個能說一篇文章.

寫在最後:

最近自學有點迷茫了, 所以想看看別人出的教程.到最後發現:學習這種事情,還是自學吧.別人消化完剩下的我下不了嘴.

學XPATH的方法還是去翻文檔, 比如:

大家有什麼關於XPATH的問題都可邀請我, 不然我都懶得查文檔,用不了多久又忘了.

如果你在Stack Overflow 提問, 也可以邀請我. 我主要回答關於BeautifulSoup, XPATH, 以及正則表達式相關的問題.


推薦閱讀:
相關文章