人生苦短,我用 Pythonhtml
前文傳送門:node
小白學 Python 爬蟲(1):開篇python
小白學 Python 爬蟲(2):前置準備(一)基本類庫的安裝git
小白學 Python 爬蟲(3):前置準備(二)Linux基礎入門github
小白學 Python 爬蟲(4):前置準備(三)Docker基礎入門數據庫
小白學 Python 爬蟲(5):前置準備(四)數據庫基礎框架
小白學 Python 爬蟲(6):前置準備(五)爬蟲框架的安裝ide
小白學 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 庫,若是沒有安裝,能夠參考前面的前置準備進行安裝。
首先須要引入 lxml 庫的 etree 模塊,接着引入 Requests 模塊,小編這裏直接以本身的博客站用做示例。
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)複製代碼
結果以下:
能夠看到結果是成功爬取,這裏咱們首先使用 requests 獲取首頁的源代碼 byte 數據流,接着使用 decode() 進行解碼,解碼後將字符串傳入 etree.HTML() 構建了一個 lxml.etree._Element 對象,接着咱們對這個對象作了 tostring() 轉換字符串而且進行打印。
注意: 這裏使用 tostring() 進行轉化字符串的時候,必定須要添加參數 encoding ,不然中文將會顯示爲 Unicode 編碼。
咱們構建完成了 Element 對象,接着咱們就能夠開始愉快的 Xpath 學習了。
咱們會用 //
開頭的 XPath 規則來選取全部符合要求的節點。示例(依然採用上面的 html ):
result_1 = html.xpath('//*')
print(result_1)複製代碼
結果以下:
[<Element html at 0x2a2810ea088>, <Element head at 0x2a2810e0788>, <Element meta at 0x2a2810d8048>, <Element meta at 0x2a2810d8088>, <Element meta at 0x2a280124188>,......複製代碼
結果太長僅截取部分。
這裏使用 * 表明匹配全部節點,也就是整個 HTML 文本中的全部節點都會被獲取。能夠看到,返回形式是一個列表,每一個元素是 Element 類型,其後跟了節點的名稱,如 html 、 head 、 meta 等,全部節點都包含在列表中了。
固然,在這裏匹配也能夠指定節點的名稱,例如獲取全部的 meta 節點:
result_2 = html.xpath('//meta')
print(result_2)複製代碼
結果以下:
[<Element meta at 0x1fc9107a2c8>, <Element meta at 0x1fc9107a6c8>, <Element meta at 0x1fc91ff8188>, <Element meta at 0x1fc91ff8108>, <Element meta at 0x1fc91ff8088>, <Element meta at 0x1fc91fc2d88>, <Element meta at 0x1fc91e73988>, <Element meta at 0x1fc91ff81c8>, <Element meta at 0x1fc91f93f08>, <Element meta at 0x1fc9203d2c8>, <Element meta at 0x1fc9203d308>, <Element meta at 0x1fc9203d348>, <Element meta at 0x1fc9203d408>, <Element meta at 0x1fc9203db08>, <Element meta at 0x1fc9203d388>, <Element meta at 0x1fc9203d3c8>, <Element meta at 0x1fc92025c08>, <Element meta at 0x1fc92025b88>, <Element meta at 0x1fc92025c48>, <Element meta at 0x1fc92025cc8>]複製代碼
這裏要選取全部 meta 節點,可使用 //
,而後直接加上節點名稱便可,調用時直接使用 xpath()
方法便可。因爲返回的是一個列表,全部要獲取特定的某個 meta 的時候,能夠直接在 [] 中加索引,例如 `[0]` 。
獲取子節點通常可使用 /
或者 //
來獲取子節點或者孫子節點。
好比如今想獲取全部的文章內容的塊,以下:
紅框所標識的內容,能夠看到 DOM 結構爲
下面的
result_3 = html.xpath('//main/article')
print(result_3)複製代碼
結果以下:
[<Element article at 0x225ef371c08>, <Element article at 0x225ef372208>, <Element article at 0x225ef3727c8>, <Element article at 0x225ef372d88>, <Element article at 0x225ef373388>, <Element article at 0x225ef373948>, <Element article at 0x225ef373f08>, <Element article at 0x225ef374508>, <Element article at 0x225ef374ac8>, <Element article at 0x225ef3750c8>, <Element article at 0x225ef375688>, <Element article at 0x225ef375c48>]複製代碼
此處的 /
是用於獲取子節點,若是想要獲取孫子節點,如
,以下圖:
則能夠這麼寫:
result_4 = html.xpath('//main//div')
print(result_4)複製代碼
結果就不貼了,太長了。
咱們能夠經過 /
和 //
來查找子節點,那麼確定有語法能夠查找父節點,否則只能向下查詢不能向上查詢就有點就有點太傻了。
父節點的查找是經過 ..
來實現的,好比咱們先找到一篇文章的圖片,如今要向上查找它的 ,以下圖:
這裏咱們經過 alt
屬性爲 小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖
的 ,而後獲取它的父節點
,而且打印他的
href
屬性,代碼以下:
result_5 = html.xpath('//img[@alt="小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖"]/../@href')
print(result_5)複製代碼
結果以下:
['/2019/12/09/1691033431/']複製代碼
同時咱們獲取父節點還可使用 parent::
。
result_6 = html.xpath('//img[@alt="小白學 Python 爬蟲(16):urllib 實戰之爬取妹子圖"]/parent::*/@href')
print(result_6)複製代碼
在選取節點的時候,咱們可使用 @
符號進行屬性過濾。
好比咱們在選取
class
爲
container
的
。而在首頁的
的子節點中,
class
爲
container
的
只有一個,代碼以下:
result_7 = html.xpath('//section/div[@class="container"]')
print(result_7)複製代碼
運行結果以下:
[<Element div at 0x251501c2c88>]複製代碼
本系列的全部代碼小編都會放在代碼管理倉庫 Github 和 Gitee 上,方便你們取用。