Python爬蟲十六式 - 第四式: 使用Xpath提取網頁內容

Xpath:簡單易用的網頁內容提取工具

學習一時爽,一直學習一直爽 !html

  Hello,你們好,我是Connor,一個從無到有的技術小白。上一次咱們說到了 requests 的使用方法。到上節課爲止,咱們已經學完了全部的 Python 經常使用的訪問庫。那麼當咱們獲取到了訪問的內容以後,咱們就應該從網頁上提取咱們想要的內容了。因此,今天咱們來說網頁內容的經常使用提取工具之一:Xpath 。相比於 BeautifulSoup 而言,Xpath 更加簡單易上手。node

1.Xpath簡介

  Xpath 是一門在 XML 文檔中查找信息的語言。XPath 用於在 XML 文檔中經過元素和屬性進行導航。他是一種路徑語言(XML Path Language),用來肯定XML文檔中某部分的位置。python

  XPath基於XML的樹狀結構,提供在數據結構樹中找尋節點的能力。起初XPath的提出的初衷是將其做爲一個通用的、介於XPointerXSL間的語法模型。可是XPath很快的被開發者採用來看成小型*查詢語言被普遍使用。好比說,當你打開一個網頁後按 F12 進行元素檢查。當你想要複製某個元素的路徑的時候,你能夠經過右鍵進行 Copy 操做。你會發現裏面有 Copy Xpath 的選項。因而可知 Xpath 使用的普遍程度。數據結構

說了這麼多Xpath使用的怎麼怎麼普遍,怎麼怎麼好用,咱們仍是來點實在的,看看在 Python 爬蟲中到底如何使用 Xpath 來抓取咱們想要的內容吧:工具


2. Xpath的安裝

  在前面的教程中,我幾乎從未提過某個庫的安裝,可是爲何在這裏我要提出如何安裝呢?緣由很簡單,Xpath只是 lxml 庫中的一個模塊,在 Python 不少庫中都提供有 Xpath 的功能,可是最基本的仍是 lxml 的這個庫。效率最高。因此,你知道了,想要使用 Xpath 那麼你就須要安裝 lxml 庫:post

pip install lxml
複製代碼

3.Xpath的語法

  其實說白了,Xpath 就是從 html 中選取節點。節點是經過沿着路徑或者經過 step 來選取的。下面,咱們將經過以下HTML文檔來進行演示:性能

html_doc ="""
<html>
    <head></head>
    <body>
        <li>
            <a href="/book_16860.html" title="總裁的新鮮小妻">
                <img src="/16860s.jpg">
            </a>
            <img src="/kukuku/images/only.png" class="topss png_bg">
                <img src="abc.png" class="topss png_bg">
            <a href="/book_16860.html">總裁的新鮮小妻子</a>
        </li>
        <li>
            <a href="/book_16861.html" title="鬥神天下">
                <img src="/16861s.jpg">
            </a>
            <img src="/kukuku/images/only.png" class="topss png_bg">
            <img src="def.png" class="topss png_bg">
            <a href="/book_16861.html">鬥神天下</a>
        </li>

    </body>
</html>"""
複製代碼

  首先,你們也都知道咱們實際上從網頁上獲取的都是字符串格式。那麼若是咱們想要經過 Xpath 來提取咱們想要的內容,咱們首先要生成 HTML 的 DOM 樹:學習

from lxml import etree

page = etree.HTML(html_doc)
複製代碼

3.1 路徑查找

  若是咱們想要使用路徑查找,那咱們首先須要知道 Xpath 的語法。Xpath 的主要語法有以下:url

表達式 描述
nodename 選取名爲nodename的子節點
/ 從根節點選取
// 從匹配選擇的當前節點選擇文檔中的節點,而不考慮它們的位置。
. 選取當前節點
.. 選取當前節點的父節點
@ 選取屬性
  • 查找當前的子節點:
In [1]: page.xpath('head')
Out[1]: [<Element head at 0x7f185bfe5b08>]
複製代碼

  當前的節點位置是在 html,因此直接查詢 head 節點能夠查詢出來,li 是html的孫節點,若是查詢 li 將返回空值:spa

In [2]: page.xpath('li')
Out[2]: []
複製代碼
  • 從根節點進行查找:
In [3]: page.xpath('/html')
Out[3]: [<Element html at 0x11208be88>]
複製代碼

  從根節點進行查找,根節點下只有一個節點 html 節點,因此從根節點查找只能查找到 html,若是查找其它內容將返回空列表:

In [4]: page.xpath('/li')
Out[4]: []
複製代碼
  • 從整個文檔全部節點查找:
In [5]: page.xpath('//li')
Out[5]:
[<Element li at 0x1128c02c8>,
 <Element li at 0x111c74108>,
 <Element li at 0x111fd2288>,
 <Element li at 0x1128da348>]
複製代碼

  從整個文檔進行查找能夠查找整個文檔中符合條件的節點,包括孫節點及如下。

  • 選取當前節點的父節點
In [6]: page.xpath('//li')[0].xpath('..')
Out[6]: [<Element body at 0x1128c0ac8>]
複製代碼
  • 選取屬性:
In [7]: page.xpath('//a')[1].xpath('@href')
Out[7]: ['/book_16860.html']
複製代碼

  選取屬性支持任意的標籤屬性,可是要注意若是選取出的節點有多個,須要指定是哪個節點的屬性。


3.2 節點查找

經過路徑查找到節點之後,就須要從超找到的節點中選取咱們須要的內容了。查找節點也有一些語法,以下:

表達式 結果
nodename[index] 選取符合要求的第 index 個元素
nodename[last()] 選取最後一個元素
nodename[position()< num] 選取前 num 個元素
nodename[@attribute] 選取帶有屬性名爲 attribute 的元素
nodename[@attribute='value'] 選取帶有屬性名爲 attribute 且 值爲 value 的元素
  • 選取第一個 img 節點的 src 屬性:
In [1]: page.xpath('//li[1]/a[1]/img[1]/@src')
Out[1]: ['/16860s.jpg']
複製代碼

  **注意:當你在選取一個節點的屬性的時候,有一點須要注意。經過[index]選取出的節點是每個符合條件的第[index]個符合條件的元素。**可是這麼說比較抽象,咱們舉個例子。例如:

In [2]: page.xpath('//li[1]') 選取全部符合 li 節點的第一個節點
Out[2]: [<Element li at 0x7fb517327ac8>]
複製代碼

  經過上面的例子咱們貌似看不出什麼,那咱們再看下面的這個例子:

In [3]: page.xpath('//li//img[1]')
Out[3]: [<Element img at 0x7f0c26328b08>, 
         <Element img at 0x7f0c26328a88>, 
         <Element img at 0x7f0c26328bc8>, 
         <Element img at 0x7f0c26328c08>]
複製代碼

  你能夠看到,咱們選取出了4個 img 節點。緣由很簡單,看下面的代碼和解釋就能明白了:

<html>
	<head></head>
	<body>
        <li>
            <a href="/book_16860.html" title="總裁的新鮮小妻">
                (一)<img src="/16860s.jpg">
            </a>
            (二)<img src="/kukuku/images/only.png" class="topss png_bg">
            (三)<img src="abc.png" class="topss png_bg">
            <a href="/book_16860.html">總裁的新鮮小妻子</a>
        </li>
        <li>
        	<a href="/book_16861.html" title="鬥神天下">
                (四)<img src="/16861s.jpg">
            </a>
            (五)<img src="/kukuku/images/only.png" class="topss png_bg">
            (六)<img src="def.png" class="topss png_bg">
            <a href="/book_16861.html">鬥神天下</a>
        </li>

    </body>
</html>
複製代碼
  1. (一)是第一個 <li> 節點的 <a> 節點裏的第一個 <img> 節點。其路徑爲 <li>/<a>/<img>
  2. (二)是第一個 <li> 節點的 <img> 節點裏的第一個 <img> 節點。其路徑爲 <li>/<img>
  3. (三)之因此沒有被選中,是由於它是 <li> 標籤下的第二個 <img> 標籤
  4. (四)(五)(六)同理
  • 選取第二個元素開始的全部節點:
In [4]: page.xpath('//img[position()>1]')
Out[4]: [<Element img at 0x7f78ba63dac8>, <Element img at 0x7f78ba63da48>]
複製代碼
  • 選取帶有指定屬性與指定值的節點:
In [5]: page.xpath('//a[@title="鬥神天下"]')
Out[5]: [<Element a at 0x7fdd0844fa48>]
複製代碼

3.3 未知節點的匹配

  當咱們匹配時會出現路徑不肯定的狀況,這個時候咱們就要涉及到匹配未知節點。匹配未知節點也有對應的語法,以下:

通配符 描述
* 匹配任何元素節點
@* 匹配任何屬性節點

匹配任何屬性節點:

In [1]: page.xpath('//li/a/*')
Out[1]: [<Element img at 0x7f83af768b08>,
         <Element img at 0x7f83af768a88>,
         <Element img at 0x7f83af768bc8>,
         <Element img at 0x7f83af768c08>]
複製代碼

匹配任何元素節點:

In [2]: page.xpath('//li/a[@*]')
Out[2]: [<Element a at 0x7ff2dcf69b08>,
         <Element a at 0x7ff2dcf69a88>,
         <Element a at 0x7ff2dcf69bc8>,
         <Element a at 0x7ff2dcf69c08>]
複製代碼

3.4 獲取節點中的文本

  經過 屬性方法能夠獲取屬性內的內容,可是位於節點之間的內容沒法獲取到,這個時候就能夠經過 text()string() 方法來得到其中的文本:

經過 text() 獲取某個節點中的文本:

In [1]: page.xpath('//li/a[3]/text()')
Out[1]: ['總裁的新鮮小妻子', '鬥神天下']
複製代碼

  能夠看到,經過 text() 屬性能夠很輕鬆的獲取標籤之間的文本。

經過 string() 獲取某個節點中的文本:

In [1]: page.xpath('string(//li[1]/a[3])')
Out[1]: '總裁的新鮮小妻子'
複製代碼

3.5 選取多個路徑

  有的時候咱們須要同時查找多個條件,這個時候你能夠經過在路徑表達式中使用管道符("|"),選取若干個路徑:

In [1]: page.xpath('//li[1]/img[2]/@src | //li[1]/a[3]/text()')
Out[1]: ['/kukuku/images/second.png', '總裁的新鮮小妻子']
複製代碼

  同時選取多個路徑並不會生成一個新的列表,只有一個列表,因此你要考慮好如何提取你的返回結果。通常狀況下仍是不建議使用多條件來進行查找,由於多種提取結果混在一個列表不利於提取,即使能夠提取,但也會增長計算量,下降程序性能。因此,儘可能不要使用這種方法。


下期預告:

  Xpath用來用去仍是那麼費勁啊,有沒有什麼別的更簡單的方法啊???固然有的,你能夠喝着美味的湯就作完你須要作的事情了。敬請期待下期——BeautifulSoup:美味的湯

  以上就是全部的 Xpath 有關的內容啦,可能並不比別人講的細,可是已經足夠你作爬蟲使用了。其實我也但願可以講的更加細緻一點,奈何我是一個正則黨,我我的不太喜歡使用Xpath,若是你真的想要深刻了解Xpth的話,推薦你到 W3C Xpath教程 >>> 去看看它們是怎麼用的。

  好了,這就是今天的內容了,我是Connor,一個從無到有的技術小白。不知道你今天又收穫了多少呢???咱們下期再見!

學習一時爽,一直學習一直爽 !


系列文章鏈接:

Python 爬蟲十六式 - 第一式:HTTP協議 >>>
Python 爬蟲十六式 - 第二式:urllib 與 urllib3 >>>
Python 爬蟲十六式 - 第三式:Requests的用法 >>>
Python 爬蟲十六式 - 第五式:BeautifulSoup,美味的湯 >>>
Python 爬蟲十六式 - 第六式:JQuery的假兄弟-pyquery >>>
Python 爬蟲十六式 - 第七式:正則的藝術 >>>
Python 爬蟲十六式 - 第八式:實例解析-全書網 >>>

相關文章
相關標籤/搜索