1、定义

xpath(XML Path Language)即xml路径语言,是一门在xml中寻找信息的语言,但同样适用于HTM文档的搜索

2、常用语法

语法规则 代表意义
/ 前面不写代表从根节点开始选取,前面写了标签,代表从当前节点选取直接子节点
// 代表从当前节点位置开始选取,选取符合要求的节点(可以是子孙节点
@ 选取属性
. 当前节点
.. 父节点
nodename 选取此节点的所有子节点

3、查找某个特定的节点或者包含某个指定的值的节点

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/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。

3、认识XML

数据格式 描述 设计目标
XML 可扩展标记语言 被设计为传输和存储数据,其焦点是数据的内容
HTML 超文本标记语言 显示数据以及如何更好显示


4、查找某个特定的节点或者包含某个指定的值的节点

路径表达式 结果
/bookstore/book[1] 选取属于 bookstore 子元素的第一个 book 元素。
/bookstore/book[last()] 选取属于 bookstore 子元素的最后一个 book 元素。
/bookstore/book[last()-1] 选取属于 bookstore 子元素的倒数第二个 book 元素。
/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。

5、选择未知节点

XPath 通配符可用来选取未知的 XML 元素。

通配符 描述
* 匹配任何元素节点。
@* 匹配任何属性节点。
node() 匹配任何类型的节点。

列出了一些路径表达式,以及这些表达式的结果

路径表达式 结果
/bookstore/* 选取 bookstore 元素的所有子元素。
//* 选取文档中的所有元素。
html/node()/meta/@* 选择html下面任意节点下的meta节点的所有属性
//title[@*] 选取所有带有属性的 title 元素。

xpath的更多语法: https://msdn.microsoft.com/zh-cn/library/ms256039(v=vs.80).aspx.aspx)

6、lxml库

  • lxml是一款高性能的Python HTML/XML解析器,可以通过xpath来快速的定位特定元素以及获取节点信息
  • 利用etree.HTML,将字符串转化为Element对象;
  • lxml python 官方文档:http://lxml.de/index.html
  • lxml 可以自动修正 html 代码;

6.1 利用etree.HTML,将字符串转化为xpath对象

  1. import requests
  2. from lxml import etree
  3. url = "https://www.baidu.com"
  4. headers = {
  5. "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
  6. }
  7. res = requests.get(url, headers=headers)
  8. # print(res.text)
  9. html = etree.HTML(res.text)
  10. print(html)

6.2 etree.tostring,自动修复element对象,返回的是一个字节对象

  1. from lxml import etree
  2. HTML = """<div>
  3. <ul>
  4. <li>
  5. <strong>one</strong>
  6. <li class='item-1'>
  7. <a href="http://fenqi.renren.com/" target="_blank">two</a>
  8. </li>
  9. <li class='item-1'>
  10. <a href="http://www.renren.com/" target="_blank">serven</a>
  11. </li>
  12. <li class='item-1'>
  13. <a href="https://www.kaixin.com" target="_blank">eight
  14. </li>
  15. </ul>"""
  16. html = etree.HTML(HTML)
  17. result = etree.tostring(html, encoding='utf-8')
  18. print(result)

6.3 利用xpath属性,获取节点或节点属性,返回的是个列表

  1. import requests
  2. from lxml import etree
  3. url = "https://www.baidu.com"
  4. headers = {
  5. "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36"
  6. }
  7. res = requests.get(url, headers=headers)
  8. html = etree.HTML(res.text)
  9. result = html.xpath("//head/title/text()")
  10. print(result)

6.4 属性多值匹配

如果某个属性的值有多个时,我们可以使用contains()函数来获取
contains(@属性名, “属性值”)
‘//li[contains(@class,”aaa”)]/a/text()’

  1. from lxml import etree
  2. text1='''
  3. <div>
  4. <ul>
  5. <li class="aaa item-0"><a href="link1.html">第一个</a></li>
  6. <li class="bbb item-1"><a href="link2.html">second item</a></li>
  7. </ul>
  8. </div>
  9. '''
  10. html=etree.HTML(text1,etree.HTMLParser())
  11. result=html.xpath('//li[@class="aaa"]/a/text()')
  12. result1=html.xpath('//li[contains(@class,"aaa")]/a/text()')
  13. print(result)
  14. print(result1)
  15. #通过第一种方法没有取到值,通过contains()就能精确匹配到节点了
  16. []
  17. ['第一个']

6.5 多属性匹配

我们还可能遇到一种情况,那就是根据多个属性确定一个节点,这时就需要同时匹配多个属性,此时可用运用and运算符来连接使用:

  1. from lxml import etree
  2. text1='''
  3. <div>
  4. <ul>
  5. <li class="aaa" name="item"><a href="link1.html">第一个</a></li>
  6. <li class="aaa" name="fore"><a href="link2.html">second item</a></li>
  7. </ul>
  8. </div>
  9. '''
  10. html=etree.HTML(text1,etree.HTMLParser())
  11. result=html.xpath('//li[@class="aaa" and @name="fore"]/a/text()')
  12. result1=html.xpath('//li[contains(@class,"aaa") and @name="fore"]/a/text()')
  13. print(result)
  14. print(result1)
  15. #
  16. ['second item']
  17. ['second item']