如何使用 Python 2 和 Python 3 中的内置库 ElementTree 等实体解析 HTML?
How to parse HTML with entities such as using builtin library ElementTree in Python 2 & Python 3?
有时您希望解析一些格式合理的 HTML 页面,但又不愿意引入额外的库依赖项,例如 BeautifulSoup 或 lxml。所以你可能会喜欢先尝试内置的 ElementTree,因为它是一个标准库,速度快(用 C 实现),并且它支持比基本的 HTMLParser 更好的接口(比如 XPATH 支持)。更不用说,HTMLParser has its own limitations.
ElementTree 会工作,直到它遇到一些默认情况下不处理的实体,例如
。
import xml.etree.ElementTree as ET
html = '''<html>
<div>Some reasonably well-formed HTML content.</div>
<form action="login">
<input name="foo" value="bar"/>
<input name="username"/><input name="password"/>
<div>It is not unusual to see in an HTML page.</div>
</form></html>'''
et = ET.fromstring(html)
运行 它在 Python 2 或 Python 3 上,你会看到这个错误:
xml.etree.ElementTree.ParseError: undefined entity: line 7, column 38
那里有一些问答,例如this one and that one。他们提示使用 ElementTree.XMLParser().parser.UseForeignDTD(True)
但我无法在 Python 3.3 和 Python 3.4.
中使用它
$ python3.3
Python 3.3.5 (v3.3.5:62cf4e77f785, Mar 9 2014, 01:12:57)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import xml.etree.ElementTree as ET
>>> ET.XMLParser().parser
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'xml.etree.ElementTree.XMLParser' object has no attribute 'parser'
>>>
受 this post 的启发,我们可以在传入的原始 HTML 内容前添加一些 XML 定义,然后 ElementTree 就可以开箱即用了。
这适用于 Python 2.6、2.7、3.3、3.4。
import xml.etree.ElementTree as ET
html = '''<html>
<div>Some reasonably well-formed HTML content.</div>
<form action="login">
<input name="foo" value="bar"/>
<input name="username"/><input name="password"/>
<div>It is not unusual to see in an HTML page.</div>
</form></html>'''
magic = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
<!ENTITY nbsp ' '>
]>''' # You can define more entities here, if needed
et = ET.fromstring(magic + html)
作为另一个替代答案,设置解析器的属性 "entity" 对我有用:
parser.entity["nbsp"] = ' '
有时您希望解析一些格式合理的 HTML 页面,但又不愿意引入额外的库依赖项,例如 BeautifulSoup 或 lxml。所以你可能会喜欢先尝试内置的 ElementTree,因为它是一个标准库,速度快(用 C 实现),并且它支持比基本的 HTMLParser 更好的接口(比如 XPATH 支持)。更不用说,HTMLParser has its own limitations.
ElementTree 会工作,直到它遇到一些默认情况下不处理的实体,例如
。
import xml.etree.ElementTree as ET
html = '''<html>
<div>Some reasonably well-formed HTML content.</div>
<form action="login">
<input name="foo" value="bar"/>
<input name="username"/><input name="password"/>
<div>It is not unusual to see in an HTML page.</div>
</form></html>'''
et = ET.fromstring(html)
运行 它在 Python 2 或 Python 3 上,你会看到这个错误:
xml.etree.ElementTree.ParseError: undefined entity: line 7, column 38
那里有一些问答,例如this one and that one。他们提示使用 ElementTree.XMLParser().parser.UseForeignDTD(True)
但我无法在 Python 3.3 和 Python 3.4.
$ python3.3
Python 3.3.5 (v3.3.5:62cf4e77f785, Mar 9 2014, 01:12:57)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import xml.etree.ElementTree as ET
>>> ET.XMLParser().parser
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'xml.etree.ElementTree.XMLParser' object has no attribute 'parser'
>>>
受 this post 的启发,我们可以在传入的原始 HTML 内容前添加一些 XML 定义,然后 ElementTree 就可以开箱即用了。
这适用于 Python 2.6、2.7、3.3、3.4。
import xml.etree.ElementTree as ET
html = '''<html>
<div>Some reasonably well-formed HTML content.</div>
<form action="login">
<input name="foo" value="bar"/>
<input name="username"/><input name="password"/>
<div>It is not unusual to see in an HTML page.</div>
</form></html>'''
magic = '''<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd" [
<!ENTITY nbsp ' '>
]>''' # You can define more entities here, if needed
et = ET.fromstring(magic + html)
作为另一个替代答案,设置解析器的属性 "entity" 对我有用:
parser.entity["nbsp"] = ' '