XPath
:XML Path Language
,一门在XML
和HTML
文档中查找信息的语言。
插件安装:
Chrome浏览器插件安装:XPath Helper
火狐浏览器插件安装:try XPath
XPath使用路径表达式来选取XML文档中的节点(集)。
表达式
描述
示例
nodename
选取此节点的所有子节点
div
//
查找所有子元素
//div
/
查找直接子元素
/div
.
选取当前节点
./div
..
选取当前节点的父节点
../div
@
选取某个节点的属性
div[@id]
谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。常见谓语表达式如下:
表达式
描述
备注
/div/div[1]
选取div下的第一个div元素
xpath下标是从1开始的
/div/div[last()]
选取div下的最后一个div元素
/div/div[position()>3]
选取div下的前两个div元素
//div[@id]
选取所有拥有id属性的div元素
//div[@id="10"]
选取所有id为10的div元素
//div[contains(@class, "price")]
选取所有class包含price的div元素
模糊匹配
*
表示通配符
通配符
描述
示例
结果
*
匹配任意节点
/div/*
选取div下的所有子元素
@*
匹配节点中的任何属性
//div[@*]
选取所有带有属性的div元素
通过在表达式中使用|
运算符,可以选取多个路径。示例:
'//div[@class="financial"] | //div[@class="john"]'
在所有使用的谓词中或选取节点时,可以使用运算符精确的选取节点
运算符
描述
实例
返回值
|
计算两个节点
//div | //dd
返回所用拥有div和dd元素的节点集
+
加法
6+4
10
-
减法
6-4
2
*
乘法
6*4
24
div
除法
8 div 2
4
=
等于
price=9
如果是,返回True,否则返回False
!=
不等于
price!=9
同上
<
小于
price<9
同上
>=
小于或等于
price<=9
同上
or
或
price=9 or price=10
有一个为真则返回True
and
和
price=9 and price=10
同为真则返回True
mod
计算除法的余数
5 mod 2
1
比如要选取一个div
节点,它的class
为"financial"
,id
为"john"
,可以使用//div[@class="financail" and id="john"]
表达式。在某些拥有同一属性名和内容的元素中选取某个元素比较有用。
contains
选取包含属性# div节点包含某个字符串的父节点下的td子节点
'//div[contains(text(), "标签文字包含某个字符串"]/../td'
tostring()
将对象转换为字符串# 使用xpath定位一个节点
s = html.xpath('//*[@id="testid"]')[0]
# s此时为<Element div at 0x2b6ffc8>对象
# 还原这个对象为html字符串
s2 = etree.tostring(s)
# s2现为:'<div id="testid">\n\t\t<h2>ÕâÀïÊǸöС±êÌâ</h2>\n\t\t<ol>\n\t\t\t<li data="one">1</li>\n\t\t\t<li data="two">2</li>\n\t\t\t<li data="three">3</li>\n\t\t</ol>\n\t\t<ul>\n\t\t\t<li code="84">84</li>\n\t\t\t<li code="104">104</li>\n\t\t\t<li code="223">223</li>\n\t\t</ul>\n\t</div>\n\t'
starts-with
'//div[starts-with(@class, "text")]'
not
排除属性# 排除包含某个属性的节点
'//tbody/tr[not(@class)]'
# 排除包含一个或两个属性的节点
'//tbody/tr[not(@class or @id)]'
# 定位语法: position()=last()-1
'//tr[@bgcolor="#FFFFFF"]/td[position()=last()-1]//a'
# normalize-space 函数删除了前部和尾部的空格, 并且把连续的空格串替换为一个单一的空格
'//*[starts-with(normalize-space(text()), "数读《共建“一带一路”倡议:进展、贡献和展望")]'
使用 preceding-sibling
选取之前的兄弟节点,following-sibling
选取之后的兄弟节点,例如:
# 选取 class 为 prompt 的 div 节点前的所有 class 为 post 的同级 div 节点
r.xpath('//div[@class="prompt"]/preceding-sibling::div[@class="post"]')
# 选取 class 为 prompt 的 div 节点后的第一个兄弟节点
r.xpath('//div[@class="prompt"]/following-sibling::div[1]')
节点名字可使用 name()
变量获取:
# 选取 div 下所有不是 p 标签的标签
r.xpath('//div/*[name()!="p"]')
使用 ancestor::
。
# 选取文本为 “办公电话” 的标签的 td 祖先标签的父级标签下的第二个子 td 标签下的文字
r.xpath('string(//*[text()="办公电话"]/ancestor::td/../td[2])')
参考:
lxml
是一个HTML/XML
的解析器,解析和提取网页中的数据。它和正则一样,也是通过C
语言实现的,是一款高性能的解析器。
from lxml import etree
# 对字符串进行解析,同response对象
text = "some web source text..."
html = etree.HTML(text)
# 此时information是一个列表对象(xpath函数返回的永远是一个列表),要选取具体的数据需要给出下标
information = html.xpath('//div[@id="john"]//text()')
# 打印第一个
print(information[0])
# 对网页文件进行解析
html_element = etree.parse('somefile.html')
html = etree.tostring(html_element, encoding='utf-8').decode('utf-8')
etree.parse
方法中的parser
参数可以传递解析器,如果不指定默认为XML
解析器,如果遇到不规范的HTML
代码导致解析错误,可以自己创建HTML
解析器;text()
方法,获取属性通过@属性名
方法;xpath
函数获取子元素,应该在斜杠前加一个.
,代表是从当前元素下获取,如./a[@class="test"]
。手机扫一扫
移动阅读更方便
你可能感兴趣的文章