前言
你就会发现xpath语句才是正确的从xml或html中抽取信息的标准流程化语言,而即使是功能还算强大的css selector选择器,其实也不过是xpath语句的精简版。lxml模块对xpath语句有着很好的支持:
from lxml import etree
selector = etree.HTML(html)
html_e = selector.xpath('//title')
此外lxml还可以很方便的去构建一个xml或者lxml文本:
from lxml import etree
root = etree.Element('root')
child_1 = etree.SubElement(root, 'child_1')
child_1.set('a', '1')
child_1.text = 'this is a text'
child_2 = etree.SubElement(root, 'child_2')
print(etree.tostring(root, pretty_print=True))
实际上xml几乎是可以表达任何结构信息的,从简单的html到复杂的语法树。而基于xpath我们可以实现对于非常复杂的结构信息的精准信息搜索定位等操作。
关于xml谁是element谁是属性并没有特别的标准了,很可能实际上完全是两个相同的结构信息会有不同的xml结构表达,这方面各个具体实现领域有不同的考量,但在实践上还是有很多参考指导建议的,这个感兴趣的可以看下这个网页 。
lxml类似于beautifulsoup也提供了find和find_all方法,但还是推荐读者使用xpath方法,实际上据说lxml里面的find和find_all方法也是基于lxml的xpath方法的,推荐读者多多使用xpath方法,熟悉xpath语法。
xpath方法一般会返回一个列表,不过如果你xpath语句使用 string
包装了的话,就会返回一个字符串,这个要注意下。
关于具体的使用下面有时间慢慢写上一些。
如何按照xpath删除元素
参考了 这个网页 。
def remove_tag_by_xpath(tree, xpath):
for bad in tree.xpath(xpath):
bad.getparent().remove(bad)
return tree
xpath简明教程
下面主要通过各个例子简要介绍xpath语法之,参考了 阮一峰的这篇文章 和菜鸟教程的xpath教程。
基本东西简单了解下即可,然后多看例子吧。
/what 基本路径表达,下个节点
//what 基本路径表达,任意位置的下个节点
这里 /
表示在下个节点中匹配, //
下个或所有子节点匹配。
//div[@id='what'] 根据id定位
//div[@id='what']/a[1] 根据id定位后找下面的第一个a标签
//div[@id='what']/a[*] 根据id定位后找下面的所有a标签
这里 *
表示所有的意思。
//div[@name] 找具有name属性的div标签
//div[@name='what'] 找name属性等于what的div标签
//*[contains(@class,'what')] 找某个标签class属性有 what NOTICE: 这里的意思是有,多个class属性也是可以匹配的 class="what what_what"
//div[@class='what'] 那个目标标签的class属性就是what,也就是匹配的是 class="what"
//*[@id="list"]//dd[*]/a[@href and @title] 找id=list的标签下面的所有dd标签下面的a标签,a标签必须有href和title属性。
//title[@*] 选择title,随意属性,但title标签必须有属性
选择title
//title
这是选择到了文档中任意位置的 title 标签, /
开头的话会选择根节点,这不太好用。
选择title包含的文本
//title/text()
按照id选择
//div[@id='post-date']/text()
上面例子的意思是选择一个div标签,其有id属性 post-date
,如果div改为 *
则为随便什么标签名字。
继续往下选
//*[@id='js_profile_qrcode']/div/p[1]/span/text()
选择目标标签的属性
////*[@id='js_profile_qrcode']//a/@href
string
对于选择的节点(注意如果返回的是节点集 nodeset将只取第一个),将所有的节点(也就是包括子节点)的文本抽取出来并合并。
string(//div[@class="lemma-summary"])
如果你想提取本element节点下所有的问题:
e.xpath('string(.)')
这里 .
的意思是选取当前节点,而 ..
是选取当前节点的父节点。