爬虫 - xpath

xpath 常用规则

|表达式     |功能                                         |
|-----------|---------------------------------------------|
|nodename	|选取此节点的所有子节点                       |
|/			|从根节点选取(取子节点)                     |
|//			|从匹配的节点中选择子节点(不需要考虑位置)   |
|.			|选取当前节点                                 |
|..			|选取当前节点的父节点                         |
|@			|选取属性                                     |
|*			|匹配任何元素节点                             |
|@*			|匹配任何属性节点                             |
|node()		|匹配任何类型的节点							  |

常用实例

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 id="item_1">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">测试1</li>
        </ul>
    </div>
</body>
</html>'''

html = etree.HTML(html_text)
result = html.xpath('//li')  # 查找所有的 li 标签
print(result)
result = html.xpath('//li/*')  # 查找 li 标签的子标签
print(result)
result = html.xpath('//li/a')  # 查找 li 标签下的 a 标签
print(result)
result = html.xpath('//li/..')  # 查找 li 标签的父级标签
print(result)
result = html.xpath('//li[@class="item_2"]')  # 按 class 查找
print(result)
result = html.xpath('//li[@id="item_1"]')  # 按 id 查找
print(result)

# 获取属性
result = html.xpath('//li/text()')  # 查找 li 标签的文本内容
print(result)
result = html.xpath('//li/a/@href')  # 查找 li 标签下的 a 标签的 href 属性
print(result)


函数

# 模糊查找
result = html.xpath('//li[starts-with(@class, "item")]/text()')  # 模糊查找 class 以 item 起始的 li 标签
print(result)
result = html.xpath('//li[ends-with(@class, "item")]/text()')  # 模糊查找 class 以 item 结束的 li 标签
print(result)
result = html.xpath('//li[contains(@class, "2")]/text()')  # 模糊查找 class 中有 2 的 li 标签
print(result)
result = html.xpath('//li[contains(text(), "测试")]/text()')  # 模糊查找显示文本中包含测试的 li 标签
print(result)

谓词

根据数组下标查找


# 注意 index 是从 1 开始的
result = html.xpath('//li[1]/text()')  # 查找第 1 个 li 标签
print(result)
result = html.xpath('//li[last()]/text()')  # 查找最后 1 个 li 标签
print(result)
result = html.xpath('//li[last()-1]/text()')  # 查找倒数第 2 个 li 标签
print(result)
result = html.xpath('//li[position()=1]/text()')  # 查找第 1 个 li 标签
print(result)

特例

比如:<div><p>1<p></div> <div><p>2<p></div>

两个 p 标签,分布在两个 div 中,不是兄弟关系,

在各自的兄弟族谱中,都是第一个,因此,两个 p 标签都能通过 p[1] 进行查找。

轴(Axes)

名称 功能
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>Title</title>
</head>
<body>
<article>
  <h6>标题</h6>
  <p>paragraph1</p>
  <p>paragraph2</p>
  <ul class="list">
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
    <li>item 4</li>
  </ul>
</article>
</body>
</html>'''

html = etree.HTML(html_text)
result = html.xpath('//li[1]/ancestor::*')  # 查找 li 标签的父级标签,从 html 开始
print(result)
result = html.xpath('//li[1]/ancestor::ul')  # 查找 li 标签的父级标签中的 ul 标签
print(result)
result = html.xpath('//li[1]/ancestor::ul/attribute::*')  # 查找 ul 标签的所有属性
print(result)

result = html.xpath('//li[1]/namespace::*')  # 查找 xml 命名空间
print(result)

逻辑运算(与或非)

result = html.xpath('//li[contains(text(), "1") or contains(text(), "2")]')
print(result)
result = html.xpath('//li[not(contains(text(), "1"))]')
print(result)
result = html.xpath('//li[contains(text(), "1") and contains(text(), "item")]')
print(result)

posted on 2024-12-06 15:46  疯狂的妞妞  阅读(4)  评论(0编辑  收藏  举报

导航