python爬虫xpath提取数据_Python爬虫之数据解析(XPath)

  • Post author:
  • Post category:python


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.谓语

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

/bookstore/book[1]:选取属于 bookstore 子元素的第一个 book 元素。注意位置顺序是从1开始的,和python不一样!

/bookstore/book[last()]:选取属于 bookstore 子元素的最后一个 book 元素。

/bookstore/book[last()-1]:选取属于 bookstore 子元素的倒数第二个 book 元素。

/bookstore/book[position()<3]:选取最前面的两个属于 bookstore 元素的子元素的 book 元素。

//title[@lang]:选取拥有 lang 属性的 title 元素。

//title[@lang=’eng’]:选取 lang属性值为’eng’的 title 元素。

/bookstore/book[@price>35.00]:选取 bookstore子元素中满足条件的book 元素,条件:price属性的值须大于 35.00。

3.XPath的运算符

加法:+

减法:-

乘法:*

除法:div

=:等于

!=:不等于

<:小于

<=:小于或等于

>:大于

>:大于或等于

or:或

and:与

mod:计算除法的余数

4.XPath的轴

轴可定义相对于当前节点的节点集。

语法:轴名称::节点[谓语]

常用的轴:

ancestor:选取当前节点的所有先辈节点(父、祖父等)。

ancestor-or-self:选取当前节点的所有先辈节点(父、祖父等)以及当前节点本身。

attribute:选取当前节点的所有属性。

self:选取当前节点。

child:选取当前节点的所有子节点。

parent:选取当前节点的父节点。

descendant:选取当前节点的所有后代节点(子、孙等)。

descendant-or-self:选取当前节点的所有后代节点(子、孙等)以及当前节点本身。

示例:

//li[@data=”one”]/ancestor::div:选取属性data=”one”的li节点的所有div祖先节点。

//li[@data=”one”]/ancestor::*:选取属性data=”one”的li标签的所有祖先节点。

//div[@id=”testid”]/attribute::*:选取id=”testid”的div节点的所有属性值。

//div[@id]/self::div[@data-h]/attribute::*:选取含id属性和data-h属性的div标签的所有属性值

//div[@id=”testid”]/child::*:选取id=”testid”的div节点的所有子节点。

//li[@data=”one”]/parent::ol/li[last()]/text():选取属性data=”one”的li节点的父节点ol,其最后一个li子节点的文本值。

注意:由于每个元素节点只有唯一的一个父节点,所以“parent::父节点”等价于“parent::*” 。

5.XPath常用函数

contains ()函数:

//div[ contains(@class, ‘in’) ]:选择class属性值中包含有’in’字符串的div节点。

text()函数:节点的文本值

//a[text()=’baidu’]:选取文本值等于’baidu’的a节点。

//a/text():获取a节点文本内容。

last()函数:

/bookstore/book[last()]:选取属于 bookstore 子节点的最后一个 book 节点。

position()函数:返回节点的索引位置(从1开始)

/bookstore/book[position()<=3]:选取属于 bookstore 子节点的前三个 book 节点。

starts-with()函数:

//div[starts-with(@class,’in’)]:选择class属性值以字符串’in’开头的div节点。

ends-with()函数:

//div[ends-with(@class,’in’)]:选择class属性值以字符串’in’结尾的div节点。

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 = ”’

Harry Potter

J K. Rowling

杰克罗琳

2005

29.99

”’

# 使用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)

# 返回值:

# J K. Rowling

参考文献: