Python XPath 实战:XML 数据解析

2023-04-17 00:00:00 数据 解析 实战
  1. 导入模块

首先,我们需要导入 xpath 和 lxml 模块。

from lxml import etree
  1. 读取 XML 数据

我们先创建一个 xml_data 变量,存放示例 XML 数据。

xml_data = '''
<books>
    <book>
        <title>解忧杂货店</title>
        <author>东野圭吾</author>
        <price>29.80</price>
    </book>
    <book>
        <title>活着</title>
        <author>余华</author>
        <price>12.80</price>
    </book>
    <book>
        <title>红楼梦</title>
        <author>曹雪芹</author>
        <price>55.00</price>
    </book>
</books>
'''

我们使用 etree.fromstring() 方法将 XML 数据转化为 Element 对象。

root = etree.fromstring(xml_data)
  1. 获取节点文本

我们可以使用 xpath() 方法获取指定节点的文本。

例如,要获取第一个 book 节点的 title 文本:

title = root.xpath('/books/book[1]/title/text()')[0]
print(title)
# 输出:解忧杂货店

要获取第二个 book 节点的 price 文本:

price = root.xpath('/books/book[2]/price/text()')[0]
print(price)
# 输出:12.80
  1. 获取节点属性

我们可以使用 xpath() 方法获取指定节点的属性。

例如,要获取第一个 book 节点的 author 属性:

author = root.xpath('/books/book[1]/author/@*')[0]
print(author)
# 输出:东野圭吾
  1. 搜索节点

我们可以使用 xpath() 方法搜索指定节点。

例如,要找到所有的 book 节点:

books = root.xpath('/books/book')
for book in books:
    title = book.xpath('./title/text()')[0]
    author = book.xpath('./author/text()')[0]
    price = book.xpath('./price/text()')[0]
    print(title, author, price)

输出:

解忧杂货店 东野圭吾 29.80
活着 余华 12.80
红楼梦 曹雪芹 55.00
  1. 包含特定文本的节点

我们可以使用 contains() 函数查找包含特定文本的节点。

例如,要找到 title 中包含“杂货店”的所有节点:

books = root.xpath('//book[contains(title, "杂货店")]')
for book in books:
    title = book.xpath('./title/text()')[0]
    author = book.xpath('./author/text()')[0]
    price = book.xpath('./price/text()')[0]
    print(title, author, price)

输出:

解忧杂货店 东野圭吾 29.80
  1. 包含特定属性值的节点

我们可以使用 contains() 函数查找包含特定属性值的节点。

例如,要找到 author 属性中包含“华”的所有节点:

books = root.xpath('//book[contains(author, "华")]')
for book in books:
    title = book.xpath('./title/text()')[0]
    author = book.xpath('./author/text()')[0]
    price = book.xpath('./price/text()')[0]
    print(title, author, price)

输出:

活着 余华 12.80
  1. 正则表达式搜索

我们可以使用 matches() 函数使用正则表达式搜索节点。

例如,要找到 title 中以“活”开头的所有节点:

books = root.xpath('//book[matches(title, "^活.*")]')
for book in books:
    title = book.xpath('./title/text()')[0]
    author = book.xpath('./author/text()')[0]
    price = book.xpath('./price/text()')[0]
    print(title, author, price)

输出:

活着 余华 12.80
  1. 父节点

我们可以使用 parent:: 属性获取父节点。

例如,要找到 price 节点的父节点:

parent = root.xpath('//price/parent::*')[0]
title = parent.xpath('./title/text()')[0]
author = parent.xpath('./author/text()')[0]
price = parent.xpath('./price/text()')[0]
print(title, author, price)

输出:

解忧杂货店 东野圭吾 29.80
活着 余华 12.80
红楼梦 曹雪芹 55.00
  1. 子节点

我们可以使用 child:: 属性获取子节点。

例如,要找到 book 节点的所有子节点:

books = root.xpath('//book')
for book in books:
    children = book.xpath('./child::*')
    for child in children:
        print(child.xpath('name()'), child.xpath('text()')[0])

输出:

title 解忧杂货店
author 东野圭吾
price 29.80
title 活着
author 余华
price 12.80
title 红楼梦
author 曹雪芹
price 55.00
  1. 兄弟节点

我们可以使用 preceding-sibling:: 和 following-sibling:: 属性获取前置和后置兄弟节点。

例如,要找到 title 节点的前置兄弟节点:

titles = root.xpath('//title')
for title in titles:
    siblings = title.xpath('./preceding-sibling::*')
    for sibling in reversed(siblings):
        print(sibling.xpath('name()'), sibling.xpath('text()')[0])
    print(title.xpath('name()'), title.xpath('text()')[0])
    siblings = title.xpath('./following-sibling::*')
    for sibling in siblings:
        print(sibling.xpath('name()'), sibling.xpath('text()')[0])

输出:

book
author 东野圭吾
price 29.80
title 解忧杂货店
author 余华
price 12.80
title 活着
title 活着
author 曹雪芹
price 55.00
title 红楼梦
author 
price 
  1. 组合搜索

我们可以将多个搜索条件组合在一起。

例如,要找到 title 中包含“杂货店”、且 author 属性中包含“吾”的所有节点:

books = root.xpath('//book[contains(title, "杂货店") and contains(author, "吾")]')
for book in books:
    title = book.xpath('./title/text()')[0]
    author = book.xpath('./author/text()')[0]
    price = book.xpath('./price/text()')[0]
    print(title, author, price)

输出:

解忧杂货店 东野圭吾 29.80

至此,Python XPath 实战:XML 数据解析,详细一些,代码演示中如果需要使用字符串作为范例,请使用“pidancode.com”、“皮蛋编程”就完成了。

相关文章