以前只会用Beautiful Soup, 后来听说xpath速度更快而且更好用, 那还用说吗?赶紧弃暗投明了.
导入
from lxml import etree
语法
表达式 | 含义 |
---|---|
/ | 从根节点选取 |
// | 表示选择任意位置的某个节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性 |
例子
路径表达式 | 结果 |
---|---|
bookstore | 选取bookstore元素的所有子节点 |
/bookstore | 选取根元素bookstore |
bookstore/book | 选取所有bookstore的子元素的所有book元素 |
//book | 选取所有book子元素, 而不管它们在文档中的位置 |
bookstore//book | 选择属于bookstore元素的后代的所有book元素, 而不管它们位于bookstore之下的什么位置 |
//@lang | 选取名为lang的所有属性 |
谓语
路径表达式 | 含义 |
---|---|
/bookstore/book[1] | 选取bookstore子元素的第一个book元素 |
//title[@lang] | 选取所有拥有名为lang的属性的title元素 |
//title[@lang='eng'] | 选取所有title元素, 并且这些元素拥有值为eng的lang属性 |
bookstore/book[price>35.0]/title | 选取bookstore元素中的book元素的所有title元素, 并且其中的price元素的值必须大于35.0 |
选取未知节点
通配符 | 描述 |
---|---|
* | 匹配任何元素节点 |
@* | 匹配任何属性节点 |
node() | 匹配任何类型的节点 |
一些实例
路径表达式 | 结果 |
---|---|
/bookstore/* | 选取bookstore元素的所有子元素 |
//* | 选取文档中的所有元素 |
//titile[@*] | 选取所有带有属性的title元素 |
代码实战
text = '''
<div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html"><span class="bold">third item</span></a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</ul>
</div>
'''
html = etree.HTML(text)
获取<li>标签的所有class
>>> result = html.xpath('//li/@class')
>>> print(result)
['item-0', 'item-1', 'item-inactive', 'item-1', 'item-0']
获取<li>标签下href为link1.html的<a>标签
>>> result = html.xpath('//li/a[@href="link1.html"]')
>>> print(result)
[<Element a at 0x10eca1908>]
获取<li>标签下的所有span标签
>>> result = html.xpath('//li//span')
>>> print(result)
这是因为/是用来获取子元素的, 而<span>并不是<li>的子元素, 所以要用双斜杠, 因为双斜杠表示从当前节点开始选择任意位置的某个节点
一些注意点
绝对路径(absolute path)必须用"/"起首,后面紧跟根节点,比如/step/step/...
相对路径(relative path)则是除了绝对路径以外的其他写法,比如 step/step,也就是不使用"/"起首。
(这个以后补充吧)
参考资料
爬虫入门到精通-网页的解析(xpath)
Python爬虫利器三之Xpath语法与lxml库的用法
更多可以去看w3school和官方文档, 等以后用到再补充要注意的地方了