【python爬虫】xpath使用说明

XPath 可以在XML文档中查找信息,支持HTML,可以用来提取信息。可以把标签文本看作一个树状图,最顶层是html,第二层是head和body,body的下面是许多div,每个div可以用/[@属性=属性名]来进一步细分,也可以通过/@属性来获取对应的信息,提取双标签中的文字则可以用/text()。

安装库

sh 复制代码
pip3 install lxml

基本使用

python 复制代码
from lxml import etree  
wb_data = """  
        <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>  
             </ul>  
         </div>  
        """  
html = etree.HTML(wb_data)  
print(html)  
result = etree.tostring(html)  
print(result.decode("utf-8"))

从下面的结果来看,这里的html其实就是一个python对象,etree.tostring(html)则补全了html缺胳膊少腿的标签。

输出结果:

python 复制代码
<Element html at 0x39e58f0>  
<html><body><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>  
    </body></html>

语法

选取节点

XPath 使用路径表达式在 XML 文档中选取节点。节点是通过沿着路径或者 step 来选取的。

下面列出了最有用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点。
/ 表示子级范围
// 表示子孙后代范围
. 选取当前节点。
... 选取当前节点的父节点。
@ 根据属性具体判断某一个标签,可以通过 标签名[属性值判断式] 来定位,

示例

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

路径表达式 结果
bookstore 选取 bookstore 元素的所有子节点。
/bookstore 选取元素 bookstore。注释:假如路径起始于正斜杠( / ),则此路径始终代表到某元素的绝对路径!
bookstore/book 选取属于 bookstore 的子元素的所有 book 元素。
//book 选取所有 book 子元素,而不管它们在文档中的位置。
bookstore//book 选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。
//@lang 选取名为 lang 的所有属性。

谓语(Predicates)

谓语被嵌在方括号中,用来查找某个特定的节点或者包含某个指定的值的节点。

顺序定位

  1. 方式一:[1]
    通配标签返回的是一个列表,里面为空或者一些元素。
    xpath支持取具体值, 例如去列表的第一个元素,[1]就可以拿到;第二个值就是[2]。
    注意列表的下角标从1开始,不像python那样从0开始
  2. 方式二:position()
    position函数会返回当前的位置值,拿到值之后就可以对值进行判断选取。
    举例: 选取当前位置下的所有div标签,然后去掉第一个,取出从2开始,一直到最后 一个div标签。
    .//div[position()>1]
  3. 方式三:last()
    这个是最简单的,就是取列表的最后一个元素
    举例:
    .//div[last()]

示例

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/bookstore/book[position() < 3] 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
//title[@lang] 选取所有拥有名为 lang 的属性的 title 元素。
//title[@lang='eng'] 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。
/bookstore/book[price>35.00] 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。
/bookstore/book[price>35.00]/title 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。

选取未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

示例

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
//title[@*] 选取所有带有属性的 title 元素。

选取若干路径

通过在路径表达式中使用"|"运算符,您可以选取若干个路径。

示例

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

路径表达式 结果
//book/title | //book/price 选取 book 元素的所有 title 和 price 元素。
//title | //price 选取文档中的所有 title 和 price 元素。
/bookstore/book/title | //price 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。

与或非

通过与或非进行更严格的筛选

逻辑
关键字 and or not()
示例 .//div[@id and @class] .//div[@id or @class] .//div[not(@id)]
示例解释 同时拥有id和class属性的div 有id或者class属性的div 没有id属性的 div

常用函数

contains(属性名,值)

匹配包含对应值的标签或数据

python 复制代码
response.xpath('//a[contains(text(),"Next >")]')
response.xpath('.//div[contains(@class,"content")]')

获取某个标签的内容(基本使用),注意,获取a标签的所有内容,a后面就不用再加正斜杠,否则报错。

text()

获取文本
写法一

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('/html/body/div/ul/li/a')
print(html)
for i in html_data:
	print(i.text)

输出:

python 复制代码
<Element html at 0x12fe4b8>
first item
second item
third item
fourth item
fifth item

写法二

直接在需要查找内容的标签后面加一个/text()就行

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('/html/body/div/ul/li/a/text()')
print(html)
for i in html_data:
	print(i)

输出:

复制代码
<Element html at 0x138e4b8>
first item
second item
third item
fourth item
fifth item

parse(html文件路径)

打开读取html文件

python 复制代码
#使用parse打开html的文件
html = etree.parse('test.html')
html_data = html.xpath('//*')#打印是一个列表,需要遍历
print(html_data)
for i in html_data:
	print(i.text)

将文本转码

python 复制代码
html = etree.parse('test.html')
html_data = etree.tostring(html,pretty_print=True)
res = html_data.decode('utf-8')
print(res)

示例

打印指定路径下a标签的属性

可以通过遍历拿到某个属性的值,查找标签的内容

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('/html/body/div/ul/li/a/@href')
for i in html_data:
	print(i)

相对路径匹配

下面我们查找相对路径,例如,查找所有li标签下的a标签内容。

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('//li/a/text()')
print(html_data)
for i in html_data:
	print(i)

打印:

python 复制代码
['first item', 'second item', 'third item', 'fourth item', 'fifth item']
first item
second item
third item
fourth item
fifth item

使用相对路径,查找一下相对路径下li标签下的a标签下的href属性的值,注意,a标签后面需要双//。

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('//li/a//@href')
print(html_data)
for i in html_data:
	print(i)

打印:

python 复制代码
['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']
link1.html
link2.html
link3.html
link4.html
link5.html

相对路径下跟绝对路径下查特定属性的方法类似,也可以说相同。

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('//li/a[@href="link2.html"]')
print(html_data)
for i in html_data:
	print(i.text)

打印:

python 复制代码
[<Element a at 0x216e468>]
second item

查找最后一个li标签里的a标签的href属性

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('//li[last()]/a/text()')
print(html_data)
for i in html_data:
	print(i)

打印:

python 复制代码
['fifth item']
fifth item

查找倒数第二个li标签里的a标签的href属性

python 复制代码
html = etree.HTML(wb_data)
html_data = html.xpath('//li[last()-1]/a/text()')
print(html_data)
for i in html_data:
	print(i)

打印:

python 复制代码
['fourth item']
fourth item
相关推荐
liuzhenghua662 小时前
Python任务调度模型
java·运维·python
小前端大牛马2 小时前
java教程笔记(十一)-泛型
java·笔记·python
sjtu_cjs2 小时前
Tensorrt python api 10.11.0笔记
开发语言·笔记·python
哆啦A梦的口袋呀2 小时前
深入理解系统:UML类图
开发语言·python·uml
虎冯河2 小时前
怎么让Comfyui导出的图像不包含工作流信息,
开发语言·python
葬爱家族小阿杰3 小时前
python执行测试用例,allure报乱码且未成功生成报告
开发语言·python·测试用例
xx155802862xx3 小时前
Python如何给视频添加音频和字幕
java·python·音视频
酷爱码3 小时前
Python实现简单音频数据压缩与解压算法
开发语言·python
花果山总钻风3 小时前
SQLAlchemy 中的 func 函数使用指南
python
知识中的海王4 小时前
Python html 库用法详解
开发语言·python