XPath全称是XML Path Language,即XML路径语言,用来在XML文档中查找信息,虽然是用来查找XML文档,但同样适用于HTML文档
表达式 | 描述 |
---|---|
nodename | 选取此节点的所有子节点 |
/ | 从当前节点中选取直接子节点 |
// | 从当前节点中选取子孙节点 |
. | 选取当前节点 |
. . | 选取当前节点的父节点 |
@ | 选取属性 |
1、安装 lxml 库
pip install lxml
2、案例
from lxml import etree
text = """
"""
html = etree.HTML(text)
result = etree.tostring(html)
print(result.decode('utf-8'))
etree 模块可以自动修正HTML文本
一般使用以 // 开头的XPath规则,用来选取所有符合要求的节点
from lxml import etree
html = etree.parse('.test.html', etree.HTMLParser())
result = html.xpath('//*')
print(result)
通过 / 或者 // 即可查找元素的子节点或子孙节点
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//li/a')
print(result)
1)使用 … 实现获取父节点
案例
from lxml import etree
html = etree.parse('./test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/../@class')
print(result)
2)使用 parent:: 实现获取父节点
from lxml import etree
html = etree.parse('.test.html', etree.HTMLParser())
result = html.xpath('//a[@href="link4.html"]/::*/@class'))
print(resutl)
在选取节点时,可使用@符号实现属性过滤
from lxml import etree
html = etree.parse('.test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]')
print(result)
使用XPath中的text方法可以获取节点中的文本
from lxml import etree
html = etree.parse('.test.html', etree.HTMLParser())
result = html.xpath('//li[@class="item-0"]/text()')
print(result)
使用@符号获取属性
from lxml import etree
html = etree.parse('.test.html', etree.HTMLParser())
result = html.xpath('//li/a@href')
print(result)
某些节点的某个属性可能有多个值,例如有两个值,如果用之前的那种匹配方式就无法进行,这种情况就需要用到contains方法
from lxml import etree
text = """
first item
"""
html = etree.HTML(text)
# contains方法给其中第一个参数传入属性名称,第二个参数传入属性值,只要传入的属性包含传入的属性值,就可完成匹配
result = html.xpath('//li[contains(@class, "li")]/a/text()')
print(result)
有时需要根据多个属性确定一个节点,这时需要同时匹配多个属性,使用运算符and来连接多个属性
from lxml import etree
text = """
first item
"""
html = etree.HTML(text)
# contains方法给其中第一个参数传入属性名称,第二个参数传入属性值,只要传入的属性包含传入的属性值,就可完成匹配
result = html.xpath('//li[contains(@class, "li") and @name="item"]/a/text()')
print(result)
在选择节点时,某些属性可能同时匹配了多个节点,但开发者只需要其中某一个,如第二个或者最后一个,可以使用往中括号中传入索引的方法获取特定次序的节点
from lxml import etree
text = """
"""
html = etree.HTML(text)
# 选取第一个li节点
result = html.xpath('//li[1]/a/text()')
print(result)
# 选取最后一个li节点
result = html.xpath('//li[last()]/a/text()')
print(result)
# 选取位置小于3的li节点
result = html.xpath('//li[position()<3]/a/text()')
print(result)
# 选取倒数第三个li节点
result = html.xpath('//li[las()-2)]/a/text()')
print(result)
XPath提供了很多节点轴的选择方法,包括获取子元素、兄弟元素、父元素、祖先元素等
from lxml import etree
text = """
"""
html = etree.HTML(text)
# 调用ancestor轴,可获取所有祖先节点
result = html.xpath('//li[1]/ancestor::*')
print(result)
# 获取只有div的祖先节点
result = html.xpath('//li[1]/ancestor::div')
print(result)
# 调用attribute轴,获取所有属性值,后面跟着*代表获取节点的所有属性,返回值就是li节点的所有属性值
result = html.xpath('//li[1]/attribute::*')
print(result)
# 调用child轴,获取所有直接子节点,悬着href属性为link1.html的a节点
result = html.xpath('//li[1]/child::a[@href="link1.html"]')
print(result)
# 调用descendant轴,可获取所有子孙节点,只包含span节点
result = html.xpath('//li[1]/descendant::span')
print(result)
# 调用following轴,获取当前节点之后的所有节点
result = html.xpath('//li[1]/following::*[2]')
print(result)
# 调用following-sibling轴,可获取当前节点之后的所有同级节点
result = html.xpath('//li[1]/following-sibling::*')
print(result)