- VisualStudio2022插件的安装及使用-编程手把手系列文章
- pprof-在现网场景怎么用
- C#实现的下拉多选框,下拉多选树,多级节点
- 【学习笔记】基础数据结构:猫树
XPath(XML Path Language)是一种用于在XML和HTML文档中查找信息的语言,其通过路径表达式来定位节点,属性和文本内容,并支持复杂查询条件,XPath 是许多 Web 抓取工具如 Scrapy,Selenium 等的核心技术之一 。
导入lxml.etree 。
from lxml import etree
使用etree.parse(filename, parser=None)函数返回一个树形结构 。
etree.parse()
用于解析本地XML或HTML文件,并将其转换为一个树形结构即ElementTree
对象,可以通过该对象访问文档的各个节点filename
:要解析的文件路径parser
(可选):默认情况下,parser()会根据文件扩展名自动选择合适的解析器,如.xml
文件使用XML解析器,.html使用HTML解析器使用etree.HTML(html_string, parser=None)解析网络html字符串 。
html_string
:要解析的HTML字符串parser
:(可选):默认情况下etree.HTML()
使用etree.HTMLparser()
进行解析ELement
对象,表示HTML文档的根元素,可以通过该对象访问文档各个节点使用.xpath(xpath_expression)在已经解析好的HTML文档中执行XPath查询 。
result = html_tree.xpath(xpath_expression)
xpath_expression
:XPath表达式,用于在文档中查找节点,XPath表达式可以是绝对路径或相对路径,也可以包含谓词,函数和轴操作,主要的XPath语法下面会展开讲解html_tree
:可以是 ElementTree
对象(由 etree.parse() 返回)或 Element
对象(由 etree.HTML() 返回)from lxml import etree
# 使用etree.parser()解析文件路径
parser = etree.HTMLParser(encoding='utf-8') # 以utf8进行编码
tree = etree.parse('../Learning02/三国演义.html', parser=parser)
print(tree)
#output-> <lxml.etree._ElementTree object at 0x000001A240107000>
# 使用etree.HTML()解析本地文件或网络动态HTML
# 读取文件 解析为字符串
file = open('../Learning02/三国演义.html', 'r', encoding='utf-8')
data = file.read()
root = etree.HTML(data)
print(root)
#整合
root = etree.HTML(open('../Learning02/三国演义.html', 'r', encoding='utf-8').read())
print(root)
#output-> <Element html at 0x1a23e462880>
XPath语法可以用于在XML与HTML文档中查找信息的语言 。
XPath使用路径表达式来定位文档中的节点,路径也可以分为绝对路径与相对路径 。
/
:表示从根节点开始选择,其用于定义一个绝对路径从根节点html开始查找到head,再从head下找出title标签 。
root = etree.HTML(open('../Learning02/三国演义.html', 'r', encoding='utf-8').read())
all_titles = root.xpath('/html/head/title')
for title in all_titles:
print(etree.tostring(title, encoding='utf-8').decode('utf-8'))
#output-> <title>《三国演义》全集在线阅读_史书典籍_诗词名句网</title>
相比与绝对路径,相对路径使用率更好,更好用 。
//
:表示从当前节点开始,选择文档中所有符合条件的节点,并且不考虑他们的位置root = etree.HTML(open('../Learning02/三国演义.html', 'r', encoding='utf-8').read())
all_a = root.xpath('//a')
for a in all_a:
print(a.text)
#None
#首页
#分类
#作者
#...
./
:表示当前节点,通常用于指明当前节点本身,避免混淆all_a = root.xpath('//a')
print(all_a[1].xpath('./text()')) #./表示当前的a标签
#output-> ['首页']
@
:用于选择元素的属性,而不是元素本身# 使用 @ 选择 <a> 标签的 href 属性
all_hrefs = root.xpath('//a[@href]')
for hrefs in all_hrefs:
print(etree.tostring(hrefs, encoding='unicode'))
谓语是xpath中用于进一步筛选节点的表达式,通常放在方括号[] 内,其可以基于节点的位置,属性值,文本内容或其他条件来选择特定的节点,谓语可以嵌套使用,也可以与其他谓语组合使用 。
基本语法 。
//element[condition]
element
:要选择的元素condition
:谓语中的条件,用于进一步筛选符合条件的元素位置谓语用于根据节点在兄弟节点中的位置进行选择,可以使用position()或直接指定位置编号 。
获取第一个ul标签中的第一个li标签 。
#//ul获取的是所有ul,[0]选择第一个
lis = root.xpath('//ul')[0].xpath('./li[1]')
for li in lis:
print(etree.tostring(li, encoding='unicode'))
#output-> <li><a href="/">首页</a></li>
使用last()获取最后第一个节点,和导数第二个节点 。
# 倒一个
last_li = root.xpath('//ul')[0].xpath('./li[last()]')
print(etree.tostring(last_li[0], encoding='unicode'))
# 倒二个
last_second_li = root.xpath('//ul')[0].xpath('./li[last()-1]')
print(etree.tostring(last_second_li[0], encoding='unicode'))
#output-> <li><a href="/app/">安卓下载</a></li>
#<li><a href="/book/">古籍</a></li>
使用position()获取位置进行筛选 。
# 获取前两个li标签
last_li = root.xpath('//ul')[0].xpath('./li[position()<3]')
for li in last_li:
print(etree.tostring(li, encoding='unicode'))
# 获取偶数位标签
lis = root.xpath('//ul')[0].xpath('./li[position() mod 2=0]')
for li in lis:
print(etree.tostring(li, encoding='unicode'))
属性谓语 。
属性谓语用于选择具体特定属性的节点 。
@attribute
来获取属性名称,结合条件进行筛选# 选取所有具有 href 属性的 a 元素
hrefs = root.xpath("//a[@href]")
for href in hrefs:
print(etree.tostring(href, encoding='unicode'))
class
属性值all_class = root.xpath('//@class')
print(all_class)
组合谓语 。
将多个条件组合在一起,使用逻辑运算符 and,or等来创建更复杂的谓语 。
#选取href属性值为https://example.com且class属性值为link的a元素
//a[@href='https://example.com' and @class='link']
#选取href属性值为https://example.com或https://another.com的a 元素
//a[@href='https://example.com' or @href='https://another.com']
函数谓语 。
Xpath提供了许多内置函数,来应对更复杂的筛选条件 。
contains((string1, string2)函数
string1
:要搜索的字符串string2
:要查找的字符串# 选取class包含"book"的img标签
images = root.xpath('//img[contains(@src,"book")]')
for image in images:
print(etree.tostring(image, encoding='unicode'))
starts-with(string1, string2)函数
检查一个字符串是否以指定字符的前缀开始,是返回true,否返回false 。
string1:
要检查的字符串string2:
作为前缀的字符串# 选取所有href以https://开头的a标签
all_a = root.xpath('//a[starts-with(@href,"https:")]')
for a in all_a:
print(etree.tostring(a, encoding='unicode'))
文本内容谓语 。
用于选择包含特定文本内容的节点,可以使用text()函数来提取节点的文本内容 。
# 选择使用包含"三国"文本的p标签
paragraphs = root.xpath('//p[contains(text(),"三国")]')
for p in paragraphs:
print(etree.tostring(p, encoding='unicode'))
xpath提供了多种通配符,用于在路径表达式中匹配未知的元素,属性,或任何节点.这些通配符非常有用,尤其是当不确定具体节点名称和结构的情况下 。
通配符 | 描述 |
---|---|
* | 匹配任何元素节点。 一般用于浏览器copy xpath会出现 |
@* | 匹配任何属性节点。 |
node() | 匹配任何类型的节点。 |
*
匹配任何元素节点*
是最常用的通配符之一,其可以匹配任何元素,而不需要具体标签名.这在不确定元素名称或希望选择所有类型的元素时非常有用# 选择所有 div 下的所有子元素
divs = root.xpath("//div/*")
for div in divs:
print(etree.tostring(div, encoding='unicode'))
@*
匹配任何属性节点@*
用于匹配任何属性节点,而不用指定具体属性名称,在你不确定属性名称或希望选择所有属性时非常有用# 选择所有 a 元素的所有属性
all_a = root.xpath('//a/@*')
for a in all_a:
print(a)
node()
匹配任何类型的节点node()
是一个更通用的通配符,其能匹配任何类型节点,包括元素节点,文本节点,属性节点,注释节点等等,其在需要选择不仅仅是元素节点是十分有用# 选择所有 ul 下的所有子节点(包括文本节点)
nodes = root.xpath('//ul/node()')
print(nodes)
#output-> ['\n ', <Element li at 0x2009621d800>, '\n,...]
在之前的学习中我们首先学习了re正则表达式,其次学习了更加便捷的bs4,哪为何还要学习XPath解析呢,接下来我们将它们的优点和适用场景进行对比学习 。
工具 | 优点 | 缺点 | 适用场景 |
---|---|---|---|
XPath |
强大的路径表达能力,支持层级结构和条件查询 | 学习曲线较陡,对不规范 HTML 容错性较差 | 结构化良好的 XML/HTML,复杂查询 |
re |
灵活性高,适合处理纯文本中的模式匹配 | 不适合解析 HTML/XML,可读性差 | 从纯文本中提取特定模式的数据 |
BeautifulSoup |
易于使用,容错性强,适合初学者 | 性能稍低,功能有限 | 不规范的 HTML,简单数据提取,网页抓取 |
最后此篇关于Xpath解析及其语法的文章就讲到这里了,如果你想了解更多关于Xpath解析及其语法的内容请搜索CFSDN的文章或继续浏览相关文章,希望大家以后支持我的博客! 。
编辑:为什么这被否决了?我真的不知道...顺便说一句 ../不起作用,因为我不想要 Table 的父级但实际上想要 ../td+1 我不知道这是否可能? 嗨,大家好。 我手头有一个相当复杂的问题..
我很难找到需要单击的输入(复选框)元素的 xpath。我正在尝试使用其他跨度元素来定位它。元素包含 Angular 属性,不知道这是否重要? 元素的结构如下: Company name
我正在尝试构建一个包含许多 XPath 作为参数的 DSL。我是 XPath 的新手,我需要一个 XPath 语法中从未使用过的字符,这样我就可以在脚本的一行中分隔 n 个 XPath。我的问题:哪些
使用xpath在父标签内找到特定标签: 输入样例:
我需要构造一个通用XPath来找到正确的节点,其中的标准是日期和时间。例如查找“ 5 May”,“ 12:17:44”的节点 XML具有日期和时间标签。 不方便地,日期标签仅在当天的第一次出现时填充。
我正在尝试获取xPath几个月内两个日期之间的差异。 几天之内我就没问题了(1127) days-from-duration(xs:date('2012-06-17')-xs:date('2009-0
我试图选择一个包含一段文本的元素,但是我不想选择包含该文本加上其他文本的元素。我通常会使用text()='abc def',但是这个特定元素在前后都包含空格。 这是一个示例片段:
亲爱的,您能帮我用这个XPATH吗?可以说我有以下HTML代码 text value1 value2 text 我需要构建一
我正在尝试提取带有排除项的 xpath,但无法执行此操作。 (//div[@class='row site country-names']/following-sibling::div)[1]/di
response.xpath('//*[@id="blah"]//text()') 假设我的html是 This is a simple text foo and this is after tag.
除了那些具有"//ul/li[not(@*)][count(*)=0]"父项的人以外,我需要全部接受。我已经尝试过,但是不幸的是它不起作用。 有谁知道,我该怎么处理? 提前致谢。 最佳答案 我认为您需
我使用XPath的问题是,每当我使用“子字符串”功能时,我只会得到一个匹配项,而我想全部获得它们。 另一个问题是,每当我使用“子字符串”和运算符的组合时它只是行不通(没有匹配项)。 例如:http:/
我正在尝试通过其位置和属性获取项目,但不知道如何做。 我要实现的是将这一点统一起来: Xpath("//h4/a[contains(@href,'#vuln_')]") 还有这个: Xpath
我有一个xpath如下: .//*[text()='Name:']/../child::select | .//*[text()='Name:']/../child::span 但是对我来说,它既不紧
我拼命试图在xpath中组合几个过滤器。假设我的数据如下所示: DELETE 1 This is my title my sh
我想在已经通过 xpath 设置的其他元素中使用 xpath 来指示元素的位置。 下面的一个已经通过 xpath 设置(我没有改变) //Base_Code
是否可以使用xpath直接在括号内抓取信息?还是以后再用正则表达式过滤? HTML如下所示: Product name (UN1QU3 C0D3) 使用以下Xpath表达式,我可以在此中获取所有内容:
我试图使用一个XPath表达式来选择一个节点,该节点的子节点与文档中的另一个节点匹配。 匹配将意味着该节点的所有属性都相同。因此,如果将一个节点与多个属性进行比较,则无法进行单独的属性比较。 作为示例
我想在 XPath 表达式中使用 Iverson 括号(即映射 true => 1,false => 0)。 示例:而不是书写 someNumber+(if(elem1/elem2[@attr='12
是否可以以类似方式选择节点? './tr[position() in (1, 3, 7)]' 我只找到以下解决方案: './tr[position() = 1 or position() = 3 or
我是一名优秀的程序员,十分优秀!