是否有一种全面的方法来查找HTML实体(包括外语字符)并将它们转换为十六进制编码或ElementTree接受的其他编码类型?这是最好的做法吗?
我正在解析XML的大型数据集,它使用HTML实体来编码unicode和特殊字符。我的脚本逐行传入XML文件。当我使用python ElementTree解析数据时,我收到以下错误。
ParseError: undefined entity: line 296, column 29
我已经开始构建一个字典来解析字符串并编码为十六进制。这减轻了许多错误。例如,将商标符号™
转换为™
。然而,看不到尽头。这是因为我已经开始寻找用于外语的unicode转义字符,例如'Å'和'ö'。我已经看了几个选项,下面将对它们进行描述。
xmlcharrefreplace:这没有找到外语HTML转义值。
line = line.encode('ascii', 'xmlcharrefreplace')
HTMLParser.enescape():没有用,我相信因为XML需要转义某些字符,例如'<&>'。
h = HTMLParser.HTMLParser()
line = h.unescape(line)
编码为UTF-8:我不相信,因为XML需要转义一些字符。
line = line.encode('utf-8')
BeautifulSoup:这返回了一个BeautifulSoup对象,当转换为字符串时,为每一行添加了XML版本标记,甚至在替换它时,还有一些其他类型的字符添加。
line = BeautifulSoup(line, "xml")
line = str(line).replace('<?xml version="1.0" encoding="utf-8"?>', "").replace("\n", "")
htmlentitydefs:仍设法错过很多角色。例如,仍然错过'?'然而,'=',这让我比其他选择更进一步。
from htmlentitydefs import name2codepoint
line = re.sub('&(%s);' % '|'.join(name2codepoint),
lambda m: unichr(name2codepoint[m.group(1)]), line)
答案 0 :(得分:0)
以下是我为解决这个问题所做的工作。我使用了多管齐下的方法来代替拥有一个模块或解决方案。我写了一个刮刀并用它来构建一个大字典(replacement_dict),它比我在这里发布的样本字典大。刮掉这样的网站(https://www.freeformatter.com/html-entities.html#iso88591-characters)。然后我在发送到sanitize函数的行中替换了该dict中的所有实体。从那里我使用两个软件包来刮掉包含在软件包中的剩余html实体,最后使用基本的正则表达式替换来获取html实体,这些实体似乎无法在“综合列表”中或在其他软件包中找到。这就是问题所在,是有错误的实体,甚至谷歌搜索无法提出的实体也没有这样的网站:http://www.graphemica.com。无论如何,问题解决了。所有的html实体,甚至是错误的实体都被处理掉了。代码发布在下面。也许是矫枉过正,但它最后一个都得到了!
replacement_dict = {
'§' : '§',
'õ' : 'õ',
'í' : 'í',
'¢' : '¢',
'Ô' : 'Ô',
'—' : '—',
'å' : 'å',
'½' : '½',
'Ò' : 'Ò',
'ß' : 'ß',
'ç' : 'ç',
'Ü' : 'Ü',
'Â' : 'Â',
'¦' : '¦',
'@' : "",
'≦' : "",
'&mgr;' : "",
'Å' : "A",
'&ohgr;' : "",
'&Dgr;' : ""
}
# Replace rare html entities not handled by other packages
for key, value in replacement_dict.items():
line = line.replace(key, value)
# replace further known entities using library
line = re.sub('&(%s);' % '|'.join(name2codepoint),
lambda m: unichr(name2codepoint[m.group(1)]), line)
# further replace known xml char replace to ascii
line = line.encode('ascii', 'xmlcharrefreplace')
pattern = re.compile(r"\&[A-Za-z0-9]{1,}\;")
# finally use regex to replace anyhting that looks like an html entity
line = re.sub(pattern, "", line)