小白學 Python 爬蟲(19):Xpath 基操

小白學 Python 爬蟲(19):Xpath 基操

人生苦短,我用 Python


如果我的文章對您有幫助,請關注支持下作者的公眾號:極客挖掘機,您的關注,是對小編堅持原創的最大鼓勵:)

前文傳送門:

小白學 Python 爬蟲(1):開篇

小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝

小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門

小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門

小白學 Python 爬蟲(5):前置準備(四)數據庫基礎

小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝

小白學 Python 爬蟲(7):HTTP 基礎

小白學 Python 爬蟲(8):網頁基礎

小白學 Python 爬蟲(9):爬蟲基礎

小白學 Python 爬蟲(10):Session 和 Cookies

小白學 Python 爬蟲(11):urllib 基礎使用(一)

小白學 Python 爬蟲(12):urllib 基礎使用(二)

小白學 Python 爬蟲(13):urllib 基礎使用(三)

小白學 Python 爬蟲(14):urllib 基礎使用(四)

小白學 Python 爬蟲(15):urllib 基礎使用(五)

小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖

小白學 Python 爬蟲(17):Requests 基礎使用

小白學 Python 爬蟲(18):Requests 進階操作

引言

前面兩篇我們介紹了 Requests 的使用,原本是想再來一個實戰的,正準備搞事情的時候想起來上次實戰還給自己挖了一個坑, Xpath 還沒介紹,還是乖乖的先介紹解析庫吧。

簡介

XPath ,全稱 XML Path Language ,即 XML 路徑語言,它是一門在 XML 文檔中查找信息的語言。它最初是用來搜尋 XML 文檔的,但是它同樣適用於 HTML 文檔的搜索。

首先,還是敬上 Xpath 的官方網站:https://www.w3.org/TR/xpath/all/ 。

其次,再敬上兩個還不錯的學習地址:

w3school:https://www.w3school.com.cn/xpath/index.asp

菜鳥教程:https://www.runoob.com/xpath/xpath-tutorial.html

常用路徑表達式

下面列出了最有用的路徑表達式:

表達式描述nodename選取此節點的所有子節點。/從根節點選取。//從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。.選取當前節點。..選取當前節點的父節點。@選取屬性。

注意,在使用 Xpath 之前,需要先確保安裝好 lxml 庫,如果沒有安裝,可以參考前面的前置準備進行安裝。

Xpath 演示

首先需要引入 lxml 庫的 etree 模塊,接著引入 Requests 模塊,小編這裡直接以自己的博客站用作示例。

<code>

from

lxml

import

etree

import

requests response = requests.get(

'https://www.geekdigging.com/'

) html_str = response.content.decode(

'UTF-8'

) html = etree.HTML(html_str) result = etree.tostring(html, encoding =

'UTF-8'

).decode(

'UTF-8'

)

print

(result) /<code>

結果如下:

小白學 Python 爬蟲(19):Xpath 基操

可以看到結果是成功爬取,這裡我們首先使用 requests 獲取首頁的源代碼 byte 數據流,接著使用 decode() 進行解碼,解碼後將字符串傳入 etree.HTML() 構建了一個 lxml.etree._Element 對象,接著我們對這個對象做了 tostring() 轉換字符串並且進行打印。

注意: 這裡使用 tostring() 進行轉化字符串的時候,一定需要添加參數 encoding ,否則中文將會顯示為 Unicode 編碼。

所有節點

我們構建完成了 Element 對象,接著我們就可以開始愉快的 Xpath 學習了。

我們會用 // 開頭的 XPath 規則來選取所有符合要求的節點。示例(依然採用上面的 html ):

<code>result_1 = html.xpath(

'//*'

)

print

(result_1) /<code>

結果如下:

<code>[0x2a2810ea088>, 0x2a2810e0788>, 0x2a2810d8048>, 0x2a2810d8088>, 0x2a280124188>,......
/<code>

結果太長僅截取部分。

這裡使用 * 代表匹配所有節點,也就是整個 HTML 文本中的所有節點都會被獲取。可以看到,返回形式是一個列表,每個元素是 Element 類型,其後跟了節點的名稱,如 html 、 head 、 meta 等,所有節點都包含在列表中了。

當然,在這裡匹配也可以指定節點的名稱,例如獲取所有的 meta 節點:

<code>result_2 = html.xpath(

'//meta'

)

print

(result_2) /<code>

結果如下:

<code>[0x1fc9107a2c8>, 0x1fc9107a6c8>, 0x1fc91ff8188>, 0x1fc91ff8108>, 0x1fc91ff8088>, 0x1fc91fc2d88>, 0x1fc91e73988>, 0x1fc91ff81c8>, 0x1fc91f93f08>, 0x1fc9203d2c8>, 0x1fc9203d308>, 0x1fc9203d348>, 0x1fc9203d408>, 0x1fc9203db08>, 0x1fc9203d388>, 0x1fc9203d3c8>, 0x1fc92025c08>, 0x1fc92025b88>, 0x1fc92025c48>, 0x1fc92025cc8>]
/<code>

這裡要選取所有 meta 節點,可以使用 // ,然後直接加上節點名稱即可,調用時直接使用 xpath() 方法即可。由於返回的是一個列表,所有要獲取特定的某個 meta 的時候,可以直接在 [] 中加索引,例如 [0] 。

子節點

獲取子節點一般可以使用 / 或者 // 來獲取子節點或者孫子節點。

比如現在想獲取所有的文章內容的塊,如下:

小白學 Python 爬蟲(19):Xpath 基操

紅框所標識的內容,可以看到 DOM 結構為 下面的 ,那麼這個語句可以這麼寫:

<code>result_3 = html.xpath(

'//main/article'

)

print

(result_3) /<code>

結果如下:

<code>[0x225ef371c08>, 0x225ef372208>, 0x225ef3727c8>, 0x225ef372d88>, 0x225ef373388>, 0x225ef373948>, 0x225ef373f08>, 0x225ef374508>, 0x225ef374ac8>, 0x225ef3750c8>, 0x225ef375688>, 0x225ef375c48>]
/<code>

此處的 / 是用於獲取子節點,如果想要獲取孫子節點,如 下面的 小白學 Python 爬蟲(19):Xpath 基操

,如下圖:

則可以這麼寫:

<code>result_4 = html.xpath('//main//div')
print(result_4)
/<code>

結果就不貼了,太長了。

父節點

我們可以通過 / 和 // 來查找子節點,那麼肯定有語法可以查找父節點,不然只能向下查詢不能向上查詢就有點就有點太傻了。

父節點的查找是通過 .. 來實現的,比如我們先找到一篇文章的圖片,現在要向上查找它的 ,如下圖:

小白學 Python 爬蟲(19):Xpath 基操

這裡我們通過 alt 屬性為 小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖 的 ,然後獲取它的父節點 ,並且打印他的 href 屬性,代碼如下:

<code>result_5 = html.xpath('//img[@alt="小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖"]/../@href')
print(result_5)
/<code>

結果如下:

<code>['/2019/12/09/1691033431/']
/<code>

同時我們獲取父節點還可以使用 parent:: 。

<code>result_6 = html.xpath('//img[@alt="小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖"]/parent::*/@href')
print(result_6)
/<code>

屬性過濾

在選取節點的時候,我們可以使用 @ 符號進行屬性過濾。

比如我們在選取

的子節點中, class 為 container 的
<code>result_7 = html.xpath('//section/div[@class="container"]')
print(result_7)
/<code>

只有一個,代碼如下:

運行結果如下:

<code>[0x251501c2c88>]
/<code>

示例代碼

本系列的所有代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便大家取用。

示例代碼-Github

示例代碼-Gitee

瞭解更多

收藏

舉報

極客挖掘機

。而在首頁的

的時候,可以使用 class 為 container 的


    分享到:


    相關文章: