爬虫 - 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)
疯狂的妞妞 :每一天,做什么都好,不要什么都不做!