學習一時爽,一直學習一直爽 !html
Hello,你們好,我是Connor,一個從無到有的技術小白。上一次咱們說到了 requests
的使用方法。到上節課爲止,咱們已經學完了全部的 Python 經常使用的訪問庫。那麼當咱們獲取到了訪問的內容以後,咱們就應該從網頁上提取咱們想要的內容了。因此,今天咱們來說網頁內容的經常使用提取工具之一:Xpath
。相比於 BeautifulSoup
而言,Xpath
更加簡單易上手。node
Xpath
是一門在 XML 文檔中查找信息的語言。XPath 用於在 XML 文檔中經過元素和屬性進行導航。他是一種路徑語言(XML Path Language),用來肯定XML文檔中某部分的位置。python
XPath基於XML的樹狀結構,提供在數據結構樹中找尋節點的能力。起初XPath的提出的初衷是將其做爲一個通用的、介於XPointer與XSL間的語法模型。可是XPath很快的被開發者採用來看成小型*查詢語言被普遍使用。好比說,當你打開一個網頁後按 F12
進行元素檢查。當你想要複製某個元素的路徑的時候,你能夠經過右鍵進行 Copy 操做。你會發現裏面有 Copy Xpath
的選項。因而可知 Xpath 使用的普遍程度。數據結構
說了這麼多Xpath使用的怎麼怎麼普遍,怎麼怎麼好用,咱們仍是來點實在的,看看在 Python 爬蟲中到底如何使用 Xpath
來抓取咱們想要的內容吧:工具
在前面的教程中,我幾乎從未提過某個庫的安裝,可是爲何在這裏我要提出如何安裝呢?緣由很簡單,Xpath只是 lxml
庫中的一個模塊,在 Python 不少庫中都提供有 Xpath
的功能,可是最基本的仍是 lxml
的這個庫。效率最高。因此,你知道了,想要使用 Xpath
那麼你就須要安裝 lxml
庫:post
pip install lxml
複製代碼
其實說白了,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)
複製代碼
若是咱們想要使用路徑查找,那咱們首先須要知道 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']
複製代碼
選取屬性支持任意的標籤屬性,可是要注意若是選取出的節點有多個,須要指定是哪個節點的屬性。
經過路徑查找到節點之後,就須要從超找到的節點中選取咱們須要的內容了。查找節點也有一些語法,以下:
表達式 | 結果 |
---|---|
nodename[index] | 選取符合要求的第 index 個元素 |
nodename[last()] | 選取最後一個元素 |
nodename[position()< num] | 選取前 num 個元素 |
nodename[@attribute] | 選取帶有屬性名爲 attribute 的元素 |
nodename[@attribute='value'] | 選取帶有屬性名爲 attribute 且 值爲 value 的元素 |
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>
複製代碼
<li>
節點的 <a>
節點裏的第一個 <img>
節點。其路徑爲 <li>/<a>/<img>
<li>
節點的 <img>
節點裏的第一個 <img>
節點。其路徑爲 <li>/<img>
。<li>
標籤下的第二個 <img>
標籤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>]
複製代碼
當咱們匹配時會出現路徑不肯定的狀況,這個時候咱們就要涉及到匹配未知節點。匹配未知節點也有對應的語法,以下:
通配符 | 描述 |
---|---|
* | 匹配任何元素節點 |
@* | 匹配任何屬性節點 |
匹配任何屬性節點:
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>]
複製代碼
經過 屬性方法能夠獲取屬性內的內容,可是位於節點之間的內容沒法獲取到,這個時候就能夠經過 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]: '總裁的新鮮小妻子'
複製代碼
有的時候咱們須要同時查找多個條件,這個時候你能夠經過在路徑表達式中使用管道符("|"),選取若干個路徑:
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 爬蟲十六式 - 第八式:實例解析-全書網 >>>