XPath的基本使用
xpath(XML Path Language) 是一门在XML 和 HTML文档中查找信息的语言,可用来在XML和HTML文档中对元素和属性进行遍历。
XPath节点:有七种类型的节点:元素,属性,文本,命名空间,处理指令,注释以及文档(根)节点。XML文档是被作为节点树来对待的。树的根成为文档节点或根节点。
节点之间的关系:父,子,同胞,先辈,后代,(看看名字就OK了)
通常是在网页上右击复制XPath 的绝对路径。
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore> #树根
<book>
<title lang="en">Harry Potter</title> #属性节点
<author>J K. Rowling</author> #元素节点
<year>2005</year>
<price>29.99</price>
</book>
</bookstore> #文档节点
XPath语法
使用路径表达式来选区XML文档中的节点或者节点集,这些路径表达式和我们在电脑文件系统中看到的表达式类似。
我们将在下面的例子中使用这个 XML 文档。
<?xml version="1.0" encoding="ISO-8859-1"?>
<bookstore>
<book>
<title lang="eng">Harry Potter</title>
<price>29.99</price>
</book>
<book>
<title lang="eng">Learning XML</title>
<price>39.95</price>
</book>
</bookstore>
表达式 | 描述 |
---|---|
nodename(节点名) | 选取此节点的所有子节点 |
/ 根节点 | 从根节点选取 |
bookstare/book | 选区属于bookstore的子元素中所有的book元素 |
// book | 选区所有book子元素,不考虑他们的位置 |
bookstore//book | 选取书友bookstore元素后代的所有book元素。 |
. | 选取当前节点 |
.. | 选取当前节点为父节点 |
//@lang | 选取名为lang的所有属性 |
谓语: 用来查找某个的顶的节点或者包含某个指定的值的节点
路径表达式 | 结果 |
---|---|
/bookstore/book[1] | 选取属于bookstore子元素的一个book元素 |
/bookstore/book[last()] | 最后一个book元素 |
/bookstore/book[last()-1] | 倒数第二个 |
/bookstore/book[position()< 3] | 选取最前面的两个属于 bookstore 元素的子元素的 book 元素。(❤️ 小于号加三是心形。。) |
//title[@lang] | 选取所有拥有名为 lang 的属性的 title 元素。 |
//title[@lang=‘eng’] | 选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性。 |
/bookstore/book[price>35.00] | 选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00。 |
/bookstore/book[price>35.00]/title | 选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00。 |
选取未知节点
通配符 | 描述 |
---|---|
/bookstore/* | bookstore元素的所有子元素 |
@* | 匹配任何属性节点。 |
//* | 选取文档中的所有元素 |
node() | 匹配任何类型的节点 |
//title[@*] | 选取所有带属性的title元素。 |
选取若干路径
路径表达式 | 结果 |
---|---|
//book/title | //book/price | 选取 book 元素的所有 title 和 price 元素。 |
//title | //price | 选取文档中的所有 title 和 price 元素。 |
/bookstore/book/title | //price | 选取属于 bookstore 元素的 book 元素的所有 title 元素,以及文档中所有的 price 元素。 |
lxml库
lxml是一个HTML/XML 的解析器,主要功能就是解析提取HTML/XML数据
lxml与正则表达式一样,是C来实现的,配合XPath快速定位元素和节点信息。第三方库要安装的(捣鼓好久才装上。。。作为小白还真难受。。)
通过它来解析HTML代码,并且在解析HTML代码的时候,如果HTML代码不规范,他会自动补全
from lxml import etree
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">third item</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文档
html = etree.HTML(text)
print(html) #Element html 对象
# 按字符串序列化html
result = etree.tostring(html).decode('utf-8') #不解码的话是字节型的
print(result)
>>>
<html><body><div> #自动添加了 html body节点
<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">third item</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>
</li></ul> #自动闭合 li 标签
</div>
</body></html>
从文件中读取html代码:
from lxml import etree
html = etree.parse('hello.html')
result = etree.tostring(html).decode('utf-8')
print(result)
在lxml中使用XPath语法
使用的对象
<!-- hello.html -->
<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></li>
</ul>
</div>
from lxml import etree
html = etree.parse('hello.html')
# 获取所有li标签:
result = html.xpath('//li')
print(result) #element对象的列表形式,
for i in result:
print(etree.tostring(i).decode())
# 获取所有li元素下的所有class属性的值:
result = html.xpath('//li/@class')
print(result)
# 获取li标签下href为www.baidu.com的a标签:
result = html.xpath('//li/a[@href="www.baidu.com"]')
print(result) #没有查找的返回一个空列表。
# 获取li标签下所有span标签:
result = html.xpath('//li//span')
print(result) #尽管第三行li的子标签a有这个子标签,但是 / 表示查找直接子标签,所以找不到,用 // 就好
# 获取li标签下的a标签里的所有class:
result = html.xpath('//li/a//@class')
print(result)
# 获取最后一个li的a的href属性对应的值:
result = html.xpath('//li[last()]/a/@href')
print(result)
# 获取倒数第二个li元素的内容:
result = html.xpath('//li[last()-1]/a')
print(result)
print(result[0].text) #result是一个列表,列表是没有text属性的,
# 获取倒数第二个li元素的内容的第二种方式:
result = html.xpath('//li[last()-1]/a/text()') #通常用这种,因为实际中我们是不知道这个列表有多少元素的。
print(result)
parsel模块 跟xlml一样时用来数据解析的,这个里面包含了正则,xpath。。。别不认识
data = parsel.Selector(html).getall() # 获取HTML数据
data = parsel.Selector(html).extract() # 这个打印出来的格式更好看
都是最基础的,我个人比较喜欢深究,等找到好文章我会慢慢补充的。。。。