You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Python xml模块解析HTML遇ParseError,如何无需lxml解决?

仅用Python标准库xml解析HTML的可行方案?

我尝试用Python的xml.etree.ElementTree解析Docker仓库的HTML目录页,页面结构片段如下:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Index of linux/ubuntu/dists/jammy/pool/stable/amd64/</title>
</head>
<body>
<h1>Index of linux/ubuntu/dists/jammy/pool/stable/amd64/</h1>
<hr>
<pre><a href="../">../</a>
<a href="containerd.io_1.5.10-1_amd64.deb">containerd.io_1.5.10-1_amd64.deb</a>
...
</pre><hr></body></html>

执行以下代码时抛出解析错误:

import urllib
import xml.etree.ElementTree as ET

html_doc = urllib.request.urlopen("<MY_URL>").read()
root = ET.fromstring(html_doc)

报错信息:>>> ParseError: mismatched tag: line 6, column 2

我推测是HTML里的自闭合标签(比如<meta charset="UTF-8">、<hr>)未遵循XML闭合规范导致的。用lxml库可以正常解析:

import urllib
from lxml import html

html_doc = urllib.request.urlopen("<MY_URL>").read()
root = html.fromstring(html_doc)

请问能不能只靠Python标准库的xml模块完成解析?


解决方案

Python标准库的xml.etree.ElementTree是严格的XML解析器,而HTML的标签规则(允许自闭合标签不写/)不符合XML规范,直接解析必然报错。要只用标准库完成解析,有两种可行方式:

方法1:预处理HTML,补全自闭合标签

用正则表达式把HTML里的常见自闭合标签改成XML兼容格式(添加/>),示例代码:

import urllib
import re
import xml.etree.ElementTree as ET

url = "https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/"
html_doc = urllib.request.urlopen(url).read().decode('utf-8')

# 补全meta、hr、br、img这类自闭合标签的XML格式
processed_html = re.sub(r'<(meta|hr|br|img)([^>]+?)>', r'<\1\2/>', html_doc)

root = ET.fromstring(processed_html)

注意:这种方法仅适用于结构简单的HTML,复杂页面可能存在漏处理的情况。

方法2:使用标准库的html.parser

Python自带的html.parser是专门为HTML设计的解析器,能兼容HTML的非XML规范写法,示例代码:

import urllib
from html.parser import HTMLParser

class LinkParser(HTMLParser):
    def __init__(self):
        super().__init__()
        self.links = []

    def handle_starttag(self, tag, attrs):
        if tag == 'a':
            for attr in attrs:
                if attr[0] == 'href':
                    self.links.append(attr[1])

url = "https://download.docker.com/linux/ubuntu/dists/jammy/pool/stable/amd64/"
html_doc = urllib.request.urlopen(url).read().decode('utf-8')

parser = LinkParser()
parser.feed(html_doc)

# 输出解析到的所有链接
for link in parser.links:
    print(link)

这种方法更可靠,适合绝大多数HTML场景。

内容的提问来源于stack exchange,提问作者J'e

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.13 20:55:20