Python_Xpath使用

Xpath(from lxml import etree)

一些比较好的教程网站分享:
W3School_Xpath教程
菜鸟教程_Xpath语法

1、准备工作
  • 安装:pip install lxml
    lxml安装步骤
  • 搭配的Xpath Helper工具
    下载地址:Xpath_helper 提取码:6666
2、基本使用
  • Xpaht全称 XML路径语言(XML Path Language),可以在XML文档中获取元素或者属性信息。
  • etree.HTML():将一个简单的字符串转换成<class 'lxml.etree._Element'>对象
  • etree.tostring():将一个<class 'lxml.etree._Element'>对象转换成字符串并修正HTML代码结构
  • 以下代码是简单的使用案例:
# etree.HTML():将一个简单的字符串转换成<class 'lxml.etree._Element'>对象
from lxml import etree
text = '<h2>这里是一个测试</h2>'
html = etree.HTML(text)
title = html.xpath('//h2/text()')[0]  # 获取h2标签下的文字
print(title)

# etree.tostring():将一个<class 'lxml.etree._Element'>对象转换成字符串并修正HTML代码结构
from lxml import etree
text = '<h2>这里是一个测试</h2>'
html = etree.HTML(text)
result = etree.tostring(html, encoding='utf-8')
print(type(result.decode()), result.decode())
html = etree.HTML(result.decode())
print(type(html))
title = html.xpath('//h2/text()')[0]  # 获取h2标签下的文字
print(title)
3、Xpath常用规则
表达式描述
nodename选取此节点的所有子节点
/从根节点选取(取子节点)
//从匹配的节点中选择子节点(不需要考虑位置)
.选取当前节点
. .选取当前节点的父节点
@选取属性
*匹配任何元素节点
@*匹配任何属性节点
node()匹配任何类型的节点
4、Xpath常用实例

更多详细会持续更新,下列所示是我暂时工作中比较常用到的。

  • .xpath(‘//*’):代表匹配所有节点,返回类型为列表,列表里面每一个元素都是_Element类型。
  • .xpath(‘//li’):代表匹配当前源代码下所有li节点元素
  • .xpath(‘//li/a’):代表匹配当前源代码下所有li节点下的a节点元素
  • .xpath(‘//li[@class=“item_2”]’):代表匹配当前源代码下所有li节点下的class为item_2的节点元素
  • .xpath(‘//li[@class=“item_3”]/a/text()’):代表匹配当前源代码下所有li节点下的class为item_3的节点元素下的a元素的文本
  • .xpath(‘//li[@class=“item_3”]/a/@href’):代表匹配当前源代码下所有li节点下的class为item_3的节点元素下的a元素的href属性
  • .xpath(‘//li/p[@id=“p4”]/…/@name’):代表匹配当前源代码下p节点下的id为p4元素节点的父节点li的class中name属性
  • .xpath(‘//li[contains(@class, “t4”)]/p/text()’):代表匹配当前源代码下li的class包含t4下的p标签的文本数据
  • .xpath(‘//li[contains(text(), “测试”)]/text()’):代表匹配当前源代码下li的class=test下的文本数据是否是测试
  • .xpath(‘//li[contains(@class, “t4”) and @name=“n4”]/p/text()’):代表匹配当前源代码下li的class包含t4并且name=n4下的p元素节点的文本数据
  • .xpath(‘//li[@class=“test”]/text() | //li[@class=“item”]/text()’):代表匹配当前源代码下li的class=test并且class=item下的文本数据
from lxml import etree

html_text = '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Xpath练习实例</title>
</head>
<body>
    <div id="demo">
        <ul>
            <li class="item">demo_test_1</li>
            <li class="item_2">demo_test_2</li>
            <li class="item_3"><a href="https://www.baidu.com">demo_test_3</a></li>
            <li class="t4 item" name="n4"><p id="p4">demo_test_4</p></li>
            <li class="test">测试</li>
        </ul>
    </div>
</body>
</html>'''

html = etree.HTML(html_text)
result = html.xpath('//*')  # 代表匹配当前源代码下的所有节点
print(result)
result = html.xpath('//li')  # 代表匹配当前源代码下所有li节点元素
print(result)
result = html.xpath('//li/a')  # 代表匹配当前源代码下所有li节点下的a节点元素
print(result)
result = html.xpath('//li[@class="item_2"]')  # 代表匹配当前源代码下所有li节点下的class为item_2的节点元素
print(result)
result = html.xpath('//li[@class="item_3"]/a/text()')  # 代表匹配当前源代码下所有li节点下的class为item_3的节点元素下的a元素的文本
print(result)
result = html.xpath('//li[@class="item_3"]/a/@href')  # 代表匹配当前源代码下所有li节点下的class为item_3的节点元素下的a元素的href属性
print(result)
result = html.xpath('//li/p[@id="p4"]/../@name')  # 代表匹配当前源代码下p节点下的id为p4元素节点的父节点li的class中name属性
print(result)
result = html.xpath('//li[contains(@class, "t4")]/p/text()')  # 代表匹配当前源代码下li的class包含t4下的p标签的文本数据
print(result)
result = html.xpath('//li[contains(text(), "测试")]/text()')  # 代表匹配当前源代码下li的class=test下的文本数据是否是测试
print(result)
result = html.xpath('//li[contains(@class, "t4") and @name="n4"]/p/text()')  # 代表匹配当前源代码下li的class包含t4并且name=n4下的p元素节点的文本数据
print(result)
5、Xpath按序选择

Xpath选择大致能分成三大类:正序选择、倒序选择、范围选择

  • 正序选择
    • .xpath(“//li[1]/a/text()”):选取第一个li节点,中括号中传入数字1即可。注意,这里和代码中不同,序号是以1开头的,不是以0开头的
  • 倒序选择
    • .xpath(“//li[last()]/a/text()”):选取最后一个li节点,中括号中传入last()即可
    • .xpath(“//li[last()-1]/a/text()”):选取倒数第二个li节
    • .xpath(“//li[last()-2]/a/text()”):选取倒数第三个li节
  • 范围选择
    • .xpath(“//li[position()<= 3]/a/text()”):选择位置小于等于3的li节点
from lxml import etree

html_text = '''<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Xpath练习实例2</title>
</head>
<body>
    <div id="demo">
        <ul>
            <li class="item"><a href="#">demo_test_1</a></li>
            <li class="item_2"><a href="#">demo_test_2</a></li>
            <li class="item_3"><a href="https://www.baidu.com">demo_test_3</a></li>
            <li class="t4 item" name="t4"><a href="#">demo_test_4</a></li>
            <li class="item"><a href="#">测试s</a></li>
        </ul>
    </div>
</body>
</html>'''


html = etree.HTML(html_text)
result = html.xpath("//li[1]/a/text()")  # 选取第一个li节点,中括号中传入数字1即可
print(result)
result = html.xpath("//li[last()]/a/text()")  # 选取最后一个li节点,中括号中传入last()即可
print(result)
result = html.xpath("//li[last()-1]/a/text()")  # 选取倒数第二个li节
print(result)
result = html.xpath("//li[last()-2]/a/text()")  # 选取倒数第三个li节
print(result)
result = html.xpath("//li[position()<= 3]/a/text()")  # 选择位置小于等于3的li节点
print(result)
6、Xpath节点轴选择
  • Xpath还提供了很多节点轴选择方法,例如获取子元素、获取父元素、获取兄弟元素等
  • 有关节点轴的节点集如下:
轴名称结果
ancestor选取当前节点的所有先辈(父、祖父等)。
ancestor-or-self选取当前节点的所有先辈(父、祖父等)以及当前节点本身。
attribute选取当前节点的所有属性。
child选取当前节点的所有子元素。
descendant选取当前节点的所有后代元素(子、孙等)。
descendant-or-self选取当前节点的所有后代元素(子、孙等)以及当前节点本身。
following选取文档中当前节点的结束标签之后的所有节点。
following-sibling选取当前节点之后的所有兄弟节点
namespace选取当前节点的所有命名空间节点。
parent选取当前节点的父节点。
preceding选取文档中当前节点的开始标签之前的所有节点。
preceding-sibling选取当前节点之前的所有同级节点。
self选取当前节点。
from lxml import etree

html_text = '''
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Xpath练习实例3</title>
</head>
<body>
    <div id="demo">
        <ul>
            <li class="item"><a href="#"><span>demo_test_1</span></a></li>
            <li class="item_2"><a href="#" id="d2">demo_test_2</a><a href="#">1111</a></li>
            <li class="item_3"><a href="https://www.baidu.com">demo_test_3</a></li>
            <li class="t4 item" name="t4"><a href="#">demo_test_4</a></li>
            <li class="item"><a href="#">测试s</a></li>
        </ul>
    </div>
</body>
</html>'''

html = etree.HTML(html_text)
result = html.xpath('//li[1]/a/span/ancestor::*')  # 调用ancestor获取当前节点的所有父辈,祖先
print(result)
result = html.xpath('//li[1]/a/span/ancestor-or-self::*')  # 调用ancestor-or-self获取当前节点的所有父辈,祖先,包括自己
print(result)
result = html.xpath('//li[1]/a/span/ancestor::div')  # 调用ancestor获取只有div的祖先节点
print(result)
result = html.xpath('//li[last()-1]/attribute::*')  # 调用attribute获取当前节点的所有属性
print(result)
result = html.xpath('//li[2]/child::*')  # 调用child获取当前节点的所有子元素
print(result)
result = html.xpath('//li[2]/child::a[@id="d2"]')  # 调用child获取当前节点的所有子元素中选中的元素
print(result)
result = html.xpath('//li[1]/descendant::*')  # 调用descendant获取当前节点的所有后代元素
print(result)
result = html.xpath('//li[1]/following::*[2]/text()')  # 调用following轴,获取当前节点之后的所有节点,这里我们虽然使用的是*匹配,但又加了索引选择,所以只获取了第二个后续节点
print(result)
result = html.xpath('//li[1]/following-sibling::*')  # 调用following-sibling轴,获取当前节点之后的所有兄弟节点
print(result)
result = html.xpath('//li[1]/namespace::*')  # 调用namespace轴,获取当前节点所有命名空间节点
print(result)
result = html.xpath('//li[1]/parent::*')  # 调用parent轴,获取当前节点的父亲节点
print(result)
result = html.xpath('//li[1]/preceding::*')  # 调用preceding轴,获取Head的所有节点
print(result)
result = html.xpath('//li[3]/preceding-sibling::*')  # 调用preceding-sibling轴,获取当前节点之前的所有同级节点
print(result)
result = html.xpath('//li[last()]/a/self::*/text()')  # 调用self轴,获取当前节点的数据
print(result)

总结

以上便是我觉得xpath技术在实际工作中比较常用的方法,其中可能还会有欠缺,如果在接下来的实际操作中,有用到其他的案例,也会继续在这里进行添加。当然如果文章中有不对的地方,欢迎评论区留言进行指导,我会及时更改。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值