爬虫之XPath的用法 您所在的位置:网站首页 网络爬虫具体应用 爬虫之XPath的用法

爬虫之XPath的用法

2024-06-01 00:17| 来源: 网络整理| 查看: 265

Xpath简介

XPath (XML Path Language)是一门在 HTML\XML 文档中查找信息的语言,可用来在 HTML\XML 文档中对元素和属性进行遍历。在Python爬虫中, XPath 我们可以利用快速地定位 HTML\XML 响应中的特定元素以及获取节点的信息,并且通常情况下会比使用正则表达式提取更简单而且更高效。

Xpath常用规则 表达式描述nodename选取此节点的所有子节点/从当前节点选取直接子节点//从当前节点选取子孙节点.选取当前节点. .选取当前节点的父节点text()选取文本@选取属性*匹配任何元素节点@*匹配任何属性节点node()匹配任何类型的节点

请看以下示例:

表达式描述bookstore选取bookstore元素的所有子节点/bookstore选取根元素 bookstore。bookstore/book选取属于 bookstore 的子元素的所有 book 元素。//book选取所有 book 子元素,而不管它们在文档中的位置。bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置。//@lang选取名为 lang 的所有属性。//title/text()选取所有 title 元素的文本。/bookstore/*选取 bookstore 元素的所有子元素。//*选取文档中的所有元素。//title[@*]选取所有带有属性的 title 元素。 获取节点信息 from lxml import etree text = ''' first item second item third item fourth item fifth item ''' html = etree.HTML(text) #从文件加载HTML #html = etree.parse('test.html', etree.HTMLParser()) result = etree.tostring(html).decode('utf-8') print(result) ret = html.xpath('//li/a') #所有li的a节点 ret = html.xpath(' //a[@href="link1.html"]/../@class ') #通过父节点获取class属性 print(ret)

etree.HTML() 可以接收str或bytes类型数据,并将其转换为Elements对象,etree模块可以自动修正HTML文本,我们用tostring() 即可输出修正后的HTML代码,但结果是bytes类型,所以用decode() 将它转成str类型

属性匹配

我们在选取的时候,可以用@进行属性过滤,例如我们想要选取class为item-1的li节点时:

from lxml import etree html = etree.HTML(text) ret = html.xpath('//li[@class="item-1"]') print(ret)

,通过中括号内加属性名和属性值的方式,过滤不要的东西,输出结果:

[, ] 文本获取

利用xpath中的text() 方法可以获取节点中的文本

from lxml import etree html = etree.HTML(text) ret = html.xpath('text()') print(ret)

输出结果:

[]

从结果可以看到。我们并没有获取到任何文本,只获取到了一个换行符,这是因为XPath中text()前面是/,而此处/的含义是选取直接子节点,很明显li的直接子节点都是a节点,文本都是在a节点内部的,所以这里匹配到的结果就是被修正的li节点内部的换行符,因为自动修正的li节点的尾标签换行了。

所以,我们还要其他方法,第一种:再加一层/a

from lxml import etree html = etree.HTML(text) ret = html.xpath('//li[@class="item-0"]/a/text()')

输出结果:

['first item', 'fifth item']

第二种:用// 选取所有子孙节点的文本,但结果中会有三个内容,前两个是a节点里的文本,另一个是最后一个li节点里的换行符

from lxml import etree html = etree.parse('./test.html', etree.HTMLParser()) result = html.xpath('//li[@class="item-0"]//text()') print(result)

输出结果:

['first item', 'fifth item', '\n ']

所以若想获得子孙节点内的所有文本,可以直接用//加text()的方法,这样可以保证获得最全的文本信息,只不过会包含一些换行符等字符。如果只想获取某些子孙节点下的文本,可以先选取子孙节点,在用text()的方法获取

属性获取

用@就可以获取想要的属性,假如我们要获取li节点下所有a节点的href属性:

from lxml import etree html = tree.HTML(text) ret = html.xpath('//li/a/@href') print(ret)

输出结果:

['link1.html', 'link2.html', 'link3.html', 'link4.html', 'link5.html']

通过@href就可以获得节点属性,但这个和属性匹配的方法不同。属性匹配是这样的:如[@href=“link1.html”] ,把属性名和属性值给限定住, 而此处的@href指的是获取节点的某个属性,要做好区分

属性多值匹配

如果某些节点的某个属性有多个值,如下:

from lxml import etree text = 'first item' html = etree.HTML(text) ret = html.xpath('//li[@class="li"]/a/text()') print(ret)

class属性有两个值li和li-first,按照这种办法无法输出想要的内容,此时需要用到contains()函数:

from lxml import etree text = 'first item' html = etree.HTML(text) ret = html.xpath('//li[contains(@class, "li")]/a/text()') print(ret)

用contains() 时,第一个参数传入属性名,第二个参数传入属性值,只要此属性包含传入的属性值时,就可以完成匹配

输出结果:

['first item'] 参数索引

当我们在选择的时候某些属性可能会匹配了多个节点,但我们只要其中的某个时,就可以用中括号传入索引的方法获取特定的节点:

from lxml import etree html = etree.HTML(text) html = etree.HTML(text) ret = html.xpath('//li[1]/a/text()') print(ret) ret = html.xpath('//li[last()]/a/text()') print(ret) ret = html.xpath('//li[position()


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有