美文网首页
Python爬虫之数据解析(XPath)

Python爬虫之数据解析(XPath)

作者: 哈耶卡卡 | 来源:发表于2018-12-18 16:55 被阅读0次

XPath 是一门在 XML 文档中查找信息的语言。XPath 可用来在 XML 文档中对元素和属性进行遍历,而将 HTML文档转换成 XML文档后,就可以用 XPath 查找 HTML 节点或元素。

XML 文档的特点:
XML 文档中的每个成分都是一个节点。整个文档是一个根节点;每个 XML 标签是一个元素节点;包含在 XML 元素中的文本是文本节点;每一个 XML 属性是一个属性节点;注释则属于注释节点
其中,元素节点可以包含任意的元素节点、文本节点或属性节点,而文本节点或属性节点则不能包含节点。

XPath语法的特点:
XPath 使用路径表达式在 XML 文档中进行导航
XPath 包含一个标准函数库
XPath 表达式可返回节点集、字符串、逻辑值以及数字。

常用的XPath 开发工具:
1.开源的XPath表达式编辑工具:XMLQuire(仅XML格式文件可用)。
2.Firefox插件 Try XPath。
3.Chrome插件 XPath Helper。推荐!可以直接在网页上使用xpath定位元素,非常方便。(安装详情见参考文献2

一、XPath语法介绍

1. 选取节点

下表列出了常用的路径表达式:

表达式 描述
nodename 选取此节点的所有子节点
/ 如果在路径最前面代表从根节点选取,否则表示选择某节点的子节点
// 从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
. 表示当前节点
.. 表示当前节点的父节点
@href 节点href属性的值(/@href:当前节点href属性的值;//@href:当前节点和子孙节点href属性的值)
text() 节点的文本内容(/text():当前节点的文本内容;//text():当前节点和子孙节点的文本内容)

2.谓语

谓语:用来查找某个特定的节点或者包含某个指定属性值的节点,被嵌在方括号中。

  1. /bookstore/book[1]:选取属于 bookstore 子元素的第一个 book 元素。注意位置顺序是从1开始的,和python不一样!
  2. /bookstore/book[last()]:选取属于 bookstore 子元素的最后一个 book 元素。
  3. /bookstore/book[last()-1]:选取属于 bookstore 子元素的倒数第二个 book 元素。
  4. /bookstore/book[position()<3]:选取最前面的两个属于 bookstore 元素的子元素的 book 元素。
  5. //title[@lang]:选取拥有 lang 属性的 title 元素。
  6. //title[@lang='eng']:选取 lang属性值为'eng'的 title 元素。
  7. /bookstore/book[@price>35.00]:选取 bookstore子元素中满足条件的book 元素,条件:price属性的值须大于 35.00。

3.XPath的运算符
  1. 加法:+
  2. 减法:-
  3. 乘法:*
  4. 除法:div
  5. =:等于
  6. !=:不等于
  7. <:小于
  8. <=:小于或等于
  9. >:大于
  10. >:大于或等于
  11. or:或
  12. and:与
  13. mod:计算除法的余数

4.XPath的轴

轴可定义相对于当前节点的节点集。
语法:轴名称::节点[谓语]

常用的轴:

  1. ancestor:选取当前节点的所有先辈节点(父、祖父等)。
  2. ancestor-or-self:选取当前节点的所有先辈节点(父、祖父等)以及当前节点本身。
  3. attribute:选取当前节点的所有属性。
  4. self:选取当前节点。
  5. child:选取当前节点的所有子节点。
  6. parent:选取当前节点的父节点。
  7. descendant:选取当前节点的所有后代节点(子、孙等)。
  8. descendant-or-self:选取当前节点的所有后代节点(子、孙等)以及当前节点本身。

示例:

  1. //li[@data="one"]/ancestor::div:选取属性data="one"的li节点的所有div祖先节点。
  2. //li[@data="one"]/ancestor::*:选取属性data="one"的li标签的所有祖先节点。
  3. //div[@id="testid"]/attribute::*:选取id="testid"的div节点的所有属性值。
  4. //div[@id]/self::div[@data-h]/attribute::*:选取含id属性和data-h属性的div标签的所有属性值
  5. //div[@id="testid"]/child::*:选取id="testid"的div节点的所有子节点。
  6. //li[@data="one"]/parent::ol/li[last()]/text():选取属性data="one"的li节点的父节点ol,其最后一个li子节点的文本值。
    注意:由于每个元素节点只有唯一的一个父节点,所以“parent::父节点”等价于“parent::*” 。

5.XPath常用函数
  1. contains ()函数:
    //div[ contains(@class, 'in') ]:选择class属性值中包含有’in’字符串的div节点。
  2. text()函数:节点的文本值
    //a[text()='baidu']:选取文本值等于'baidu'的a节点。
    //a/text():获取a节点文本内容。
  3. last()函数:
    /bookstore/book[last()]:选取属于 bookstore 子节点的最后一个 book 节点。
  4. position()函数:返回节点的索引位置(从1开始)
    /bookstore/book[position()<=3]:选取属于 bookstore 子节点的前三个 book 节点。
  5. starts-with()函数:
    //div[starts-with(@class,'in')]:选择class属性值以字符串’in’开头的div节点。
  6. ends-with()函数:
    //div[ends-with(@class,'in')]:选择class属性值以字符串’in’结尾的div节点。
  7. not()函数:表示否定
    //input[@name=‘identity’ and not( contains(@class,‘a’) )]:
    选择属性name=‘identity’ 并且 class属性值中不包含字符’a’的input节点。
    not()函数通常与返回值为true or false的函数组合起来用,比如contains(),starts-with()等。但有一种特别情况需注意一下://input[@id]:匹配出含有id属性的input节点;//input[not(@id)]:匹配出不含有id属性的input节点。

6.其他

1.通配符
使用通配符“*”可用来选取未知的 XML 元素。
*:匹配任何元素节点。
@*:匹配任何属性节点。
node():匹配任意类型的节点(元素、属性、文本、注释以及根节点)。

2.选取多条路径
通过在路径表达式中使用“|”运算符,可以选取多条路径。
//book/title | //book/price:选取 book 元素的所有 title 和 price 元素。
//title | //price:选取文档中的所有 title 和 price 元素。


二、xpath在python中的具体运用

lxml库是一个XML、HTML的解析器,主要用于解析和提取XML、HTML数据。lxml库先将HTML文档解析,然后就可以使用XPath 搜索或遍历HTML文档中的节点。

使用lxml解析HTML数据的两种方式:

1.解析HTML字符串:

from lxml import etree

# HTML字符串
text = '''
<bookstore>
  <book>
    <title lang="en">Harry Potter</title>
    <author>J K. Rowling</author>
    <name>杰克罗琳</name>
    <year>2005</year>
    <price>29.99</price>
  </book>
</bookstore>
'''

# 使用HTML()方法解析字符串
# HTML()默认使用的就是HTML解析器,如果遇到不规范的HTML代码,会自动补全。
html_element = etree.HTML(text)

# 解析后就可以调用xpath方法了
name = html_element.xpath('//book/name/text()')
print(name)


# 返回值:
# ['杰克罗琳']

2.直接解析HTML文件:

from lxml import etree

# 创建HTML解析器,指定解析器使用的编码格式(需要和文件编码格式一致)
parser = etree.HTMLParser(encoding='utf-8')

# parse()默认的是XML解析器,在解析HTML代码时,如果HTML代码不规范,则会报错!
# 因此需要指定解析器为HTML解析器,这样不规范的HTML代码,会自动补全!
html_element = etree.parse('./test.html', parser=parser)

#解析后就可以调用xpath方法了
name = html_element.xpath('//book/name/text()')
print(name)


# 返回值:
# ['杰克罗琳']

注意:
1.xpath返回的永远是列表,即使没有匹配到任何元素也返回的是空列表。
2.根节点和任意元素节点都可以使用xpath方法去搜索、遍历其子节点。

# tostring()方法可以将节点对象转换成字节,解码后就可以查看节点内容
author_ele = html_element.xpath('//book/author')[0]
result = etree.tostring(author_ele, encoding='utf-8').decode('utf-8')
print(result)


# 返回值:
# <author>J K. Rowling</author>&#13;

参考文献:

  1. HTML和XML的区别
  2. XPath Helper插件安装
  3. XPath 教程

相关文章

网友评论

      本文标题:Python爬虫之数据解析(XPath)

      本文链接:https://www.haomeiwen.com/subject/tpplkqtx.html