Python
基础语法
01概念
02安装
03变量
04字符串
05数
06常量与注释
07列表
08元组
09if语句
10字典
11集合
12复合数据类型对比
13推导式
14用户输入
15while循环
16函数
17类
18面向对象编程
19文件操作
20异常处理
21日期和时间
22魔术方法
23内置函数
24线程
25并发&并行
26正则表达式
27迭代器
28装饰器
29生成器
30上下文管理器
31函数式编程
32闭包
33解包
34工具库
35连接关系型数据库
36虚拟环境
37异步编程
网络爬虫
01urllib库[了解]
02requests库
03数据交换格式
04解析库
05lxml
06Beautiful Soup
07Xpath语法
08动态网页的处理
-
+
首页
05lxml
lxml 是 Python 生态中功能强大且高性能的 **XML 和 HTML 解析库**,基于 C 语言编写的 libxml2 和 libxslt 库开发,兼具底层库的高效性和 Python 接口的易用性。 广泛应用于爬虫开发、数据提取、XML 处理等场景,尤其在需要处理大型文档或复杂查询时表现突出。 ## 特性 lxml 的优势源于其底层依赖的 libxml2(XML 解析引擎)和 libxslt(XSLT 转换引擎),核心特性包括: **高性能解析** 作为 C 扩展库,lxml 的解析速度远快于纯 Python 实现的解析库(如 BeautifulSoup 纯 Python 模式、html.parser),尤其在处理 MB 级甚至 GB 级大型文档时,内存占用和耗时优势显著。 **完善的标准支持** 严格遵循 XML 和 HTML 规范,支持: - XML 1.0/1.1 及 Namespaces(命名空间); - XPath 1.0(完整支持,部分支持 XPath 2.0 特性); - XSLT 1.0(可通过 libxslt 进行 XML 转换); - XML Schema(XSD)和 DTD 验证。 **强大的容错能力** 内置的 HTML 解析器能自动修复不规范的 HTML 代码(如未闭合标签、错误嵌套、缺失属性引号等),接近浏览器的解析行为,适合处理网页中常见的 “脏 HTML”。 **多接口支持** 提供两套核心 API: - lxml.etree:通用 XML/HTML 解析接口,功能全面; - lxml.html:专为 HTML 优化的接口,提供更简洁的网页数据提取方法(如表单处理、链接提取)。 **与其他库兼容** 可作为 BeautifulSoup 的解析器(BeautifulSoup(html, 'lxml')),结合 BeautifulSoup 的易用性和 lxml 的高性能;同时支持与 XPath、CSS 选择器(通过 cssselect 扩展)配合使用。 ## 安装方法 lxml 是 C 扩展库,依赖系统中的 libxml2 和 libxslt 库,安装前需确保这些依赖已存在。 ```cmd pip install lxml --upgrade ``` ## 核心模块 ### lxml.etree lxml.etree 是 lxml 的核心模块,提供 XML 和 HTML 的解析、构建、查询和修改功能,核心对象包括: - **Element**:代表 XML/HTML 中的标签节点,支持属性访问、子节点操作; - **ElementTree**:代表整个文档树,支持序列化、写入文件等操作; - **解析函数**:etree.HTML()(解析 HTML)、etree.XML()(解析 XML)、etree.parse()(从文件解析)。 基本用法:解析于构造文档 ```python from lxml import etree # 1. 解析 HTML 字符串(自动修复不规范标签) html_str = """ <html> <body> <h1>lxml 教程</h1> <ul> <li>解析 HTML</li> <li>XPath 查询</li> </ul> </body> """ root = etree.HTML(html_str) # 返回根节点(<html>) print(etree.tostring(root, encoding='unicode')) # 序列化文档(修复后的 HTML) # 2. 解析 XML 文件(假设存在 example.xml) tree = etree.parse('example.xml') # 从文件解析 root_xml = tree.getroot() # 获取根节点 # 3. 手动构建 XML 文档 root = etree.Element('bookstore') book = etree.SubElement(root, 'book', attrib={'id': 'b1'}) # 添加子节点及属性 etree.SubElement(book, 'title').text = 'Python 解析' etree.SubElement(book, 'price').text = '59.9' # 序列化并打印 print(etree.tostring(root, pretty_print=True, encoding='unicode')) ``` 输出结果: ```html 第一部分(解析 HTML 字符串)的输出为: <html> <body> <h1>lxml 教程</h1> <ul> <li>解析 HTML</li> <li>XPath 查询</li> </ul> </body> </html> 第三部分(手动构建 XML 文档)的输出为: <bookstore> <book id="b1"> <title>Python 解析</title> <price>59.9</price> </book> </bookstore> ``` ### 精准定位节点 lxml 对 XPath 1.0 有完整支持,通过 Element.xpath() 方法执行 XPath 表达式,返回匹配的节点或文本列表。这是 lxml 提取数据的核心方式,尤其适合复杂结构的文档。 ```python from lxml import etree html_str = """ <div class="container"> <h2>产品列表</h2> <ul class="products"> <li class="product"><a href="/p1">手机</a><span class="price">3999</span></li> <li class="product hot"><a href="/p2">电脑</a><span class="price">5999</span></li> <li class="product"><a href="/p3">平板</a><span class="price">2999</span></li> </ul> </div> """ root = etree.HTML(html_str) # 1. 提取所有产品名称(<a>标签文本) names = root.xpath('//ul[@class="products"]/li/a/text()') print(names) # ['手机', '电脑', '平板'] # 2. 提取价格大于 3000 的产品链接 links = root.xpath('//li[span[@class="price"]/text() > 3000]/a/@href') print(links) # ['/p1', '/p2'] # 3. 提取带 "hot" 类的产品信息 hot_product = root.xpath('//li[contains(@class, "hot")]')[0] print(hot_product.xpath('./a/text()')[0]) # 电脑 print(hot_product.xpath('./span/text()')[0]) # 5999 ``` 输出结果: ```txt ['手机', '电脑', '平板'] ['/p1', '/p2'] 电脑 5999 ``` ### XML 验证与转换 lxml 支持通过 XML Schema(XSD)或 DTD 验证 XML 文档的合法性,并可通过 XSLT 进行文档转换。 ```python from lxml import etree # 定义 XML Schema(XSD) xsd_str = """ <xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema"> <xsd:element name="book"> <xsd:complexType> <xsd:sequence> <xsd:element name="title" type="xsd:string"/> <xsd:element name="price" type="xsd:float"/> </xsd:sequence> </xsd:complexType> </xsd:element> </xsd:schema> """ schema = etree.XMLSchema(etree.fromstring(xsd_str)) # 验证合法 XML valid_xml = '<book><title>Python</title><price>59.9</price></book>' valid_doc = etree.fromstring(valid_xml) print(schema.validate(valid_doc)) # True(验证通过) # 验证非法 XML(price 为字符串) invalid_xml = '<book><title>Python</title><price>五十</price></book>' invalid_doc = etree.fromstring(invalid_xml) print(schema.validate(invalid_doc)) # False(验证失败) print(schema.error_log) # 打印错误信息 ``` 输出结果: ```txt True False <string>:1:0:ERROR:SCHEMASV:SCHEMAV_CVC_DATATYPE_VALID_1_2_1: Element 'price': '五十' is not a valid value of the atomic type 'xs:float'. ``` ## 注意事项 **编码处理** 解析非 UTF-8 编码的文档时,需指定编码(如 etree.HTML(html_str.encode('gbk'))),避免乱码;输出时通过 encoding='unicode' 确保文本正确。 **大型文档处理** 对于 GB 级文档,建议使用 etree.iterparse() 进行流式解析(边读边解析,不加载整个文档到内存): ```python for event, elem in etree.iterparse('large.xml', events=('end',)): if elem.tag == 'target': # 处理目标节点 print(elem.text) elem.clear() # 清理已处理节点,释放内存 ``` **与 BeautifulSoup 配合** 当需要 BeautifulSoup 的易用性同时保留 lxml 的性能时,可将 lxml 作为 BeautifulSoup 的解析器: ```python from bs4 import BeautifulSoup soup = BeautifulSoup(html_str, 'lxml') # 比默认解析器更快 ``` **HTML 与 XML 解析的区别** - etree.HTML() 会自动添加 \<html>、\<body> 等根标签(即使输入缺失); - etree.XML() 严格遵循 XML 规范,对缺失标签或不闭合标签会抛出错误。
毛林
2025年9月7日 12:11
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
Markdown文件
PDF文档(打印)
分享
链接
类型
密码
更新密码