使用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
相关产品推荐
相关产品推荐

