我正在尝试在Python 3.6.2,IPython 6.1.0,Windows 10上使用Beautiful Soup读取xml文档,但我无法正确编码。
这是我的测试 xml,以 UTF8 编码保存为文件:
<?xml version="1.0" encoding="UTF-8"?>
<root>
<info name="愛よ">ÜÜÜÜÜÜÜ</info>
<items>
<item thing="ÖöÖö">"23Äßßß"</item>
</items>
</root>
首先使用 ElementTree 检查 XML:
import xml.etree.ElementTree as ET
def printXML(xml,indent=''):
print(indent+str(xml.tag)+': '+(xml.text if xml.text is not None else '').replace('n',''))
if len(xml.attrib) > 0:
for k,v in xml.attrib.items():
print(indent+'t'+k+' - '+v)
if xml.getchildren():
for child in xml.getchildren():
printXML(child,indent+'t')
xml0 = ET.parse("test.xml").getroot()
printXML(xml0)
输出正确:
root:
info: ÜÜÜÜÜÜÜ
name - 愛よ
items:
item: "23Äßßß"
thing - ÖöÖö
现在用美丽的汤阅读相同的文件并漂亮地打印它:
import bs4
with open("test.xml") as ff:
xml = bs4.BeautifulSoup(ff,"html5lib")
print(xml.prettify())
输出:
<!--?xml version="1.0" encoding="UTF-8"?-->
<html>
<head>
</head>
<body>
<root>
<info name="愛よ">
ÜÜÜÜÜÜÜ
</info>
<items>
<item thing="ÖöÖö">
"23Äßßß"
</item>
</items>
</root>
</body>
</html>
这是错误的。使用指定的显式编码执行调用bs4.BeautifulSoup(ff,"html5lib",from_encoding="UTF-8")
不会更改结果。
行为
print(xml.original_encoding)
输出
None
所以美丽的汤显然无法检测到原始编码,即使文件是用 UTF8 编码的(根据记事本++(,并且标头信息也显示 UTF-8,而且我确实按照文档的建议安装了chardet
。
我在这里犯了错误吗?可能是什么原因造成的?
编辑: 当我在没有html5lib
的情况下调用代码时,我收到以下警告:
UserWarning: No parser was explicitly specified, so I'm using the best available HTML parser for this system ("html5lib").
This usually isn't a problem, but if you run this code on another system, or in a different virtual environment,
it may use a different parser and behave differently.
The code that caused this warning is on line 241 of the file C:UsersMy.NameAppDataLocalContinuumAnaconda2envsPython3libsite-packagesspyderutilsipythonstart_kernel.py.
To get rid of this warning, change code that looks like this:
BeautifulSoup(YOUR_MARKUP})
to this:
BeautifulSoup(YOUR_MARKUP, "html5lib")
markup_type=markup_type))
编辑2:
正如评论中所建议的,我尝试了bs4.BeautifulSoup(ff,"html.parser")
,但问题仍然存在。
然后我安装了lxml
并尝试了bs4.BeautifulSoup(ff,"lxml-xml")
,仍然相同的输出。
同样让我感到奇怪的是,即使指定像bs4.BeautifulSoup(ff,"lxml-xml",from_encoding='UTF-8')
这样的编码,xml.original_encoding
的值也与文档中编写的内容None
相反。
编辑3:
我将我的 xml 内容放入字符串中
xmlstring = "<?xml version="1.0" encoding="UTF-8"?><root><info name="愛よ">ÜÜÜÜÜÜÜ</info><items><item thing="ÖöÖö">"23Äßßß"</item></items></root>"
并且用bs4.BeautifulSoup(xmlstring,"lxml-xml")
,现在我得到了正确的输出:
<?xml version="1.0" encoding="utf-8"?>
<root>
<info name="愛よ">
ÜÜÜÜÜÜÜ
</info>
<items>
<item thing="ÖöÖö">
"23Äßßß"
</item>
</items>
</root>
所以看起来文件毕竟有问题。
发现错误,打开文件时必须指定编码:
with open("test.xml",encoding='UTF-8') as ff:
xml = bs4.BeautifulSoup(ff,"html5lib")
当我使用 Python 3 时,我认为默认情况下encoding
的值是UTF-8
的,但事实证明它是系统依赖的,并且在我的系统上它是cp1252
的。