元素树的解码实体

时间:2018-02-21 07:01:43

标签: python xml elementtree html-entities

是否有一种全面的方法来查找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)

1 个答案:

答案 0 :(得分:0)

以下是我为解决这个问题所做的工作。我使用了多管齐下的方法来代替拥有一个模块或解决方案。我写了一个刮刀并用它来构建一个大字典(replacement_dict),它比我在这里发布的样本字典大。刮掉这样的网站(https://www.freeformatter.com/html-entities.html#iso88591-characters)。然后我在发送到sanitize函数的行中替换了该dict中的所有实体。从那里我使用两个软件包来刮掉包含在软件包中的剩余html实体,最后使用基本的正则表达式替换来获取html实体,这些实体似乎无法在“综合列表”中或在其他软件包中找到。这就是问题所在,是有错误的实体,甚至谷歌搜索无法提出的实体也没有这样的网站:http://www.graphemica.com。无论如何,问题解决了。所有的html实体,甚至是错误的实体都被处理掉了。代码发布在下面。也许是矫枉过正,但它最后一个都得到了!

    replacement_dict = {
        '&sect;' : '&#x00A7;',
        '&otilde;' : '&#x00F5;',
        '&iacute;' : '&#x00ED;',
        '&cent;' : '&#x00A2;',
        '&Ocirc;' : '&#x00D4;',
        '&mdash;' : '&#x2014;',
        '&aring;' : '&#x00E5;',
        '&frac12;' : '&#x00BD;',
        '&Ograve;' : '&#x00D2;',
        '&szlig;' : '&#x00DF;',
        '&ccedil;' : '&#x00E7;',
        '&Uuml;' : '&#x00DC;',
        '&Acirc;' : '&#x00C2;',
        '&brvbar;' : '&#x00A6;',
        '&commat;' : "",
        '&lE;' : "",
        '&mgr;' : "",
        '&angst;' : "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)