網絡爬蟲--11.XPath和lxml

文章目錄

  • 一. XML
    • 1. XML 和 HTML 的區別
    • 2. XML文檔示例
    • 3. HTML DOM 模型示例
    • 4. XML的節點關系
  • 二. 什么是XPath?
    • 1. 選取節點
    • 2. 謂語(Predicates)
    • 3. 選取未知節點
    • 4. 選取若干路徑
    • 5. XPath的運算符
  • 三. lxml庫
    • 1. 初步使用
    • 2. 文件讀取
  • 四. XPath實例測試
    • 1. 獲取所有的 < li> 標簽
    • 2. 繼續獲取< li> 標簽的所有 class屬性
    • 3. 繼續獲取< li>標簽下href 為 link1.html 的 < a> 標簽
    • 4. 獲取< li> 標簽下的所有 < span> 標簽
    • 5. 獲取 < li> 標簽下的< a>標簽里的所有 class
    • 6. 獲取最后一個 < li> 的 < a> 的 href
    • 7. 獲取倒數第二個元素的內容
    • 8. 獲取 class 值為 bold 的標簽名

一. XML

有人說,我正則用的不好,處理HTML文檔很累,有沒有其他的方法?

有!那就是XPath,我們可以先將 HTML文件 轉換成 XML文檔,然后用 XPath 查找 HTML 節點或元素。

  1. XML 指可擴展標記語言(EXtensible Markup Language)
  2. XML 是一種標記語言,很類似 HTML
  3. XML 的設計宗旨是傳輸數據,而非顯示數據
  4. XML 的標簽需要我們自行定義。
  5. XML 被設計為具有自我描述性。
  6. XML 是 W3C 的推薦標準

W3School官方文檔:http://www.w3school.com.cn/xml/index.asp

1. XML 和 HTML 的區別

在這里插入圖片描述

2. XML文檔示例

<?xml version="1.0" encoding="utf-8"?><bookstore><book category="cooking"><title lang="en">Everyday Italian</title>  <author>Giada De Laurentiis</author>  <year>2005</year>  <price>30.00</price></book>  <book category="children"><title lang="en">Harry Potter</title>  <author>J K. Rowling</author>  <year>2005</year>  <price>29.99</price></book>  <book category="web"><title lang="en">XQuery Kick Start</title>  <author>James McGovern</author>  <author>Per Bothner</author>  <author>Kurt Cagle</author>  <author>James Linn</author>  <author>Vaidyanathan Nagarajan</author>  <year>2003</year>  <price>49.99</price></book><book category="web" cover="paperback"><title lang="en">Learning XML</title>  <author>Erik T. Ray</author>  <year>2003</year>  <price>39.95</price></book></bookstore>

3. HTML DOM 模型示例

HTML DOM 定義了訪問和操作 HTML 文檔的標準方法,以樹結構方式表達 HTML 文檔。
在這里插入圖片描述

4. XML的節點關系

下面一個簡單的XML例子中:

<?xml version="1.0" encoding="utf-8"?><bookstore><book><title>Harry Potter</title><author>J K. Rowling</author><year>2005</year><price>29.99</price></book></bookstore>
  1. 父(Parent) 每個元素以及屬性都有一個父。book 元素是 title、author、year 以及 price 元素的父。
  2. 子(Children)元素節點可有零個、一個或多個子。title、author、year 以及 price 元素都是 book 元素的子。
  3. 同胞(Sibling)擁有相同的父的節點。title、author、year 以及 price 元素都是同胞。
  4. 先輩(Ancestor)某節點的父、父的父,等等。title 元素的先輩是 book 元素和 bookstore 元素。
  5. 后代(Descendant)某個節點的子,子的子,等等。bookstore 的后代是 book、title、author、year 以及 price 元素。

二. 什么是XPath?

XPath (XML Path Language) 是一門在 XML 文檔中查找信息的語言,可用來在 XML 文檔中對元素和屬性進行遍歷。

W3School官方文檔:http://www.w3school.com.cn/xpath/index.asp

XPath 開發工具
開源的XPath表達式編輯工具:XMLQuire(XML格式文件可用)
Chrome插件 XPath Helper
Firefox插件 XPath Checker

1. 選取節點

XPath 使用路徑表達式來選取 XML 文檔中的節點或者節點集。這些路徑表達式和我們在常規的電腦文件系統中看到的表達式非常相似。

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

在這里插入圖片描述

在下面的表格中,我們已列出了一些路徑表達式以及表達式的結果:
在這里插入圖片描述

2. 謂語(Predicates)

謂語用來查找某個特定的節點或者包含某個指定的值的節點,被嵌在方括號中。

在下面的表格中,我們列出了帶有謂語的一些路徑表達式,以及表達式的結果:

在這里插入圖片描述

3. 選取未知節點

XPath 通配符可用來選取未知的 XML 元素。

在這里插入圖片描述
在下面的表格中,我們列出了一些路徑表達式,以及這些表達式的結果:

4. 選取若干路徑

通過在路徑表達式中使用“|”運算符,您可以選取若干個路徑。

在下面的表格中,我們列出了一些路徑表達式,以及這些表達式的結果:

在這里插入圖片描述

5. XPath的運算符

下面列出了可用在 XPath 表達式中的運算符:

在這里插入圖片描述

這些就是XPath的語法內容,在運用到Python抓取時要先轉換為xml。

三. lxml庫

lxml 是 一個HTML/XML的解析器,主要的功能是如何解析和提取 HTML/XML 數據。

lxml和正則一樣,也是用 C 實現的,是一款高性能的 Python HTML/XML 解析器,我們可以利用之前學習的XPath語法,來快速的定位特定元素以及節點信息。

lxml python 官方文檔:http://lxml.de/index.html

需要安裝C語言庫,可使用 pip 安裝:pip install lxml (或通過wheel方式安裝)

1. 初步使用

我們利用它來解析 HTML 代碼,簡單示例:

from lxml import etreetext = '''
<div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html">third item</a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a> # 注意,此處缺少一個 </li> 閉合標簽</ul></div>
'''#利用etree.HTML,將字符串解析為HTML文檔
print('------1------')
print(text)
print (type(text))html = etree.HTML(text)
print('-----2-------')
print(html)
print (type(html))# 按字符串序列化HTML文檔
result = etree.tostring(html)
print('-----3-------')
print(result)
print (type(result))

輸出結果:

------1------<div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html">third item</a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a> # 注意,此處缺少一個 </li> 閉合標簽</ul></div><class 'str'>
-----2-------
<Element html at 0x1e839453708>
<class 'lxml.etree._Element'>
-----3-------
b'<html><body><div>\n    <ul>\n         <li class="item-0"><a href="link1.html">first item</a></li>\n         <li class="item-1"><a href="link2.html">second item</a></li>\n         <li class="item-inactive"><a href="link3.html">third item</a></li>\n         <li class="item-1"><a href="link4.html">fourth item</a></li>\n         <li class="item-0"><a href="link5.html">fifth item</a> # &#27880;&#24847;&#65292;&#27492;&#22788;&#32570;&#23569;&#19968;&#20010; </li> &#38381;&#21512;&#26631;&#31614;\n     </ul>\n </div>\n</body></html>'
<class 'bytes'>

lxml 可以自動修正 html 代碼,例子里不僅會補全 li 標簽,還添加了 body,html 標簽。

2. 文件讀取

除了直接讀取字符串,lxml還支持從文件里讀取內容。我們新建一個hello.html文件:

<!-- hello.html --><div><ul><li class="item-0"><a href="link1.html">first item</a></li><li class="item-1"><a href="link2.html">second item</a></li><li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li><li class="item-1"><a href="link4.html">fourth item</a></li><li class="item-0"><a href="link5.html">fifth item</a></li></ul></div>

再利用 etree.parse() 方法來讀取文件。

from lxml import etree# 讀取外部文件 hello.html
html1 = etree.parse('./hello.html')
result1 = etree.tostring(html1, pretty_print=True)print('--------------------')
print(result1)print('-------如果是文件讀取,需要使用prase(),而不是用HTML,否則會出現下邊結果:---------')html2 = etree.HTML('./hello.html')
result2 = etree.tostring(html2, pretty_print=True)
print(result2)

運行結果:

--------------------
b'<div>\n    <ul>\n         <li class="item-0"><a href="link1.html">first item</a></li>\n         <li class="item-1"><a href="link2.html">second item</a></li>\n         <li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>\n         <li class="item-1"><a href="link4.html">fourth item</a></li>\n         <li class="item-0"><a href="link5.html">fifth item</a></li>\n     </ul>\n </div>\n'
-------如果是文件讀取,需要使用prase(),而不是用HTML,否則會出現下邊結果:---------
b'<html>\n  <body>\n    <p>./hello.html</p>\n  </body>\n</html>\n'

四. XPath實例測試

1. 獲取所有的 < li> 標簽

from lxml import etreehtml = etree.parse('hello.html')
print (type(html))  # 顯示etree.parse() 返回類型result = html.xpath('//li')print (result)  # 打印<li>標簽的元素集合
print (len(result))
print (type(result))
print (type(result[0]))

輸出結果:

<class 'lxml.etree._ElementTree'>
[<Element li at 0x21658f02608>, <Element li at 0x21658f02708>, <Element li at 0x21658f02748>, <Element li at 0x21658f02788>, <Element li at 0x21658f027c8>]
5
<class 'list'>
<class 'lxml.etree._Element'>

2. 繼續獲取< li> 標簽的所有 class屬性

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/@class')print(result)
print(type(result))

運行結果:

['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
<class 'list'>

3. 繼續獲取< li>標簽下href 為 link1.html 的 < a> 標簽


from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/a[@href="link1.html"]')print result

輸出結果:

[<Element a at 0x23b68132748>]
<class 'list'>

4. 獲取< li> 標簽下的所有 < span> 標簽

from lxml import etreehtml = etree.parse('hello.html')#result = html.xpath('//li/span')
#注意這么寫是不對的:
#因為 / 是用來獲取子元素的,而 <span> 并不是 <li> 的子元素,所以,要用雙斜杠result = html.xpath('//li//span')print(result)
print(type(result))

輸出結果:

[<Element span at 0x28d12587508>]
<class 'list'>

5. 獲取 < li> 標簽下的< a>標簽里的所有 class

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/a//@class')print(result)
print(type(result))

輸出結果:

['bold']
<class 'list'>

6. 獲取最后一個 < li> 的 < a> 的 href

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li/a//@class')print(result)
print(type(result))

輸出結果:

['link5.html']
<class 'list'>

7. 獲取倒數第二個元素的內容

from lxml import etreehtml = etree.parse('hello.html')
result = html.xpath('//li[last()-1]/a')# text 方法可以獲取元素內容
print (result[0].text)
print (type(result[0].text))

輸出結果:

fourth item
<class 'str'>

8. 獲取 class 值為 bold 的標簽名

from lxml import etreehtml = etree.parse('hello.html')result = html.xpath('//*[@class="bold"]')# tag方法可以獲取標簽名
print (result[0].tag)
print (type(result[0].tag))

輸出結果:

span
<class 'str'>

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/452027.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/452027.shtml
英文地址,請注明出處:http://en.pswp.cn/news/452027.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

實體與屬性間的劃分原則

為了簡化E-R圖的處置&#xff0c;現實世界的事物能作為屬性對待的&#xff0c;盡量作為屬性對待。 兩條準則&#xff1a; &#xff08;1&#xff09;作為屬性&#xff0c;不能再具有需要描述的性質。屬性必須是不可分的數據項&#xff0c;不能包含其他屬性。 &#xff08;2&…

編程開發之--java多線程學習總結(5)

4、對繼承自Runnable的線程進行鎖機制的使用 package com.lfy.ThreadsSynchronize;import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReentrantLock;public class TicketSellSolution4 implements Runnable {private static int num 50;//創建一個…

軟件測試不是一個功能

今天在工作中我對一個同事說&#xff0c;PyDev 2.5.0現在對TDD&#xff08;測試驅動開發&#xff09;提供了很酷的支持了。我并不是一個對TDD很癡迷的倡導者&#xff0c;對其它事物也一樣&#xff0c;但仍不免激起了一場討論。這個家伙&#xff0c;讓我們暫叫他約翰&#xff0c…

Linux 操作系統基礎知識

1.操作系統總體介紹 ?CPU&#xff1a; 就像人的大腦&#xff0c;主要負責相關事情的判斷以及實際處理的機制。查詢指令&#xff1a; cat /proc/cpuinfo?內存&#xff1a; 大腦中的記憶區塊&#xff0c;將皮膚、眼睛等所收集到的信息記錄起來的地方&#xff0c;以供CPU進行判斷…

Transaction 那點事兒,Spring事務管理

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 Transaction 也就是所謂的事務了&#xff0c;通俗理解就是一件事情。從小&#xff0c;父母就教育我們&#xff0c;做事情要有始有終&…

網絡爬蟲--12.【XPath實戰】獲取百度貼吧中的圖片

用XPath來做一個簡單的爬蟲&#xff0c;我們嘗試爬取某個貼吧里的所有帖子&#xff0c;并且將該這個帖子里每個樓層發布的圖片下載到本地。 #codingutf-8 import requests from lxml import etree import jsonclass Tieba:def __init__(self,tieba_name):self.tieba_name tie…

合并分ER圖產生的沖突

合并分E-R圖 各個局部應用所面向的問題不同&#xff0c;各個子系統的E-R圖之間必定會存在許多不一致的地方&#xff0c;稱之為沖突。 子系統E-R圖之間的沖突主要有三類&#xff1a; ①屬性沖突 ②命名沖突 ③結構沖突①屬性沖突 屬性域沖突&#xff0c;即屬性值的類型、取值范圍…

8.類定義、屬性、初始化和析構

類定義 類 是一個獨立存放變量(屬性/方法)的空間 封裝&#xff1a; 類可以把各種對象組織在一起&#xff0c;作為類的屬性&#xff0c;通過 . (點)運算符來調用類中封裝好的對象 屬性&#xff1a; 變量在類中稱為屬性&#xff0c;但是類中的屬性不僅僅只包含變量&#x…

GPL以及Copyleft協議使用率下降明顯

根據最新的協議數據分析&#xff0c;不光是GPL&#xff0c;另外一些copyleft&#xff08;AGPL&#xff0c;LGPL 等等&#xff09;協議的使用率在不斷下降&#xff0c;并且下降的速度越來越快。 這結果是在意料之中的&#xff0c;因為GPL非常的復雜。越來越多的個人和企業將選擇…

概念模型和關系模型

ER模型&#xff08;邏輯模型&#xff09; ER模型的基本元素是&#xff1a;實體、聯系和屬性 實體&#xff1a;是一個數據對象&#xff0c;指應用中可以區別的客觀存在的事物。&#xff08;ER模型中的實體往往是指實體集&#xff09; 實體集&#xff1a;指同一類實體構成的集合…

iOS AutoLayout使用技巧

關于ContentCompressionResistance&#xff0c; ContentHugging運用 如下圖效果圖&#xff0c;兩個Label并列在同一排上&#xff0c;左邊label自適應&#xff0c;右邊label&#xff08;紅色&#xff09;要使得內容全部展示&#xff0c;如果左邊label內容很少&#xff0c;那么右…

網絡爬蟲--13.數據提取之JSON與JsonPATH

文章目錄一. 前言二. JSON三. json.loads()四. json.dumps()五. json.dump()六. json.load()七. JsonPath八. JsonPath與XPath語法對比九. 案例分析一. 前言 JSON(JavaScript Object Notation) 是一種輕量級的數據交換格式&#xff0c;它使得人們很容易的進行閱讀和編寫。同時…

vs2017生成sqlserver 2017項目出現.Net SqlClient Data Provider: Msg 10343

一、使用vs2017生成sqlserver 2017項目時由于添加的程序集(CLR集成&#xff0c;可以參考后面給出的鏈接進行理解) &#xff0c;由于安全權限的配置不正確引發以下的問題: SQL72014: .Net SqlClient Data Provider: Msg 10343, Level 14, State 1, Line 1 針對帶有 SAFE 或 EXT…

數據庫系統常用的存取方法

1. B樹索引存取方法 2. Hash索引存取方法 3. 聚簇存取方法

創建型模式二:工廠方法模式

1. 工廠模式介紹 工廠模式&#xff08;Factory Pattern&#xff09;的意義就跟它的名字一樣&#xff0c;在面向對象程序設計中&#xff0c;工廠通常是一個用來創建其他對象的對象。工廠模式根據不同的參數來實現不同的分配方案和創建對象。 在工廠模式中&#xff0c;我們在創建…

spring 的4種事務管理(1種編程式+3種聲明式)

見&#xff1a;http://blog.csdn.net/sinat_25926481/article/details/48208619 Spring的4種事務管理&#xff08;1種編程式事務三種聲明事務&#xff09; 一、Spring事務的介紹 二、編程式事務xml的配置 注入后直接在service層調用模板的方法使用 三、基于AOP方式的聲明式事務…

如何創造出更優秀的用戶體驗?

對于互聯網公司來說&#xff0c;用戶體驗起到至關重要的作用&#xff0c;能否給用戶留下深刻的印象&#xff1b;開發出的產品是否實用、易用&#xff1f;等等這些都是開發者必將思考的話題。當有用性一樣的時候&#xff0c;大家的競爭重點就是易用性了&#xff0c;這就是互聯網…

java并發編程實戰-第三章-對象的共享

3.1可見性 首先我們需要知道的是&#xff0c;java的線程都有自己獨立的緩存&#xff0c;線程之間進行共享變量的交互是通過自身和緩存和主存的交互實現的。如果線程的每次更改緩存都刷入主存&#xff0c;主存每次被一個線程的緩存修改&#xff0c;都通知所有的線程刷新自身的緩…

GitHub(從安裝到使用)

一、安裝Git for Windows&#xff08;又名msysgit&#xff09; 下載地址: https://git-for-windows.github.io/ 在官方下載完后&#xff0c;安裝到Windows Explorer integration的時候&#xff0c;將選項中將“Git Bash here”和“Git GUI here”打對勾。 然后就一直next直到Fi…

Spring事務配置的五種方式和spring里面事務的傳播屬性和事務隔離級別、不可重復讀與幻讀的區別

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到教程。 spring事務配置的五種方式 前段時間對Spring的事務配置做了比較深入的研究&#xff0c;在此之間對Spring的事務配置雖說也配置過&#x…