在Python中将HTML实体转换为ASCII

4 投票
4 回答
8992 浏览
提问于 2025-04-15 13:14

我需要用Python把任何HTML实体转换成它的ASCII等价物。我的用途是清理一些用来制作邮件的HTML,以便从HTML创建纯文本邮件。

现在,我只知道如何从这些实体创建Unicode,而我需要的是ASCII(我想是这样),这样纯文本邮件才能正确显示像重音字符这样的内容。我觉得一个基本的例子就是HTML实体“& aacute;”或者说á被编码成ASCII。

而且,我甚至不确定ASCII是否是我在纯文本邮件中需要的。可以看出,我对这些编码的东西完全搞不清楚。

4 个回答

1

你可以使用 htmlentitydefs 这个包:

import htmlentitydefs
print htmlentitydefs.entitydefs['aacute']

简单来说,entitydefs 就是一个字典,你可以在 Python 提示符下打印出来看看:

from pprint import pprint 
pprint htmlentitydefs.entitydefs
8

这里有一个完整的实现,它还处理了unicode的html实体。你可能会觉得这个很有用。

它返回的是一个包含unicode的字符串,而不是纯粹的ascii字符。不过,如果你想要纯ascii字符,可以修改替换操作,把这些实体替换成空字符串。

def convert_html_entities(s):
    matches = re.findall("&#\d+;", s)
    if len(matches) > 0:
        hits = set(matches)
        for hit in hits:
            name = hit[2:-1]
            try:
                entnum = int(name)
                s = s.replace(hit, unichr(entnum))
            except ValueError:
                pass

    matches = re.findall("&#[xX][0-9a-fA-F]+;", s)
    if len(matches) > 0:
        hits = set(matches)
        for hit in hits:
            hex = hit[3:-1]
            try:
                entnum = int(hex, 16)
                s = s.replace(hit, unichr(entnum))
            except ValueError:
                pass

    matches = re.findall("&\w+;", s)
    hits = set(matches)
    amp = "&"
    if amp in hits:
        hits.remove(amp)
    for hit in hits:
        name = hit[1:-1]
        if htmlentitydefs.name2codepoint.has_key(name):
            s = s.replace(hit, unichr(htmlentitydefs.name2codepoint[name]))
    s = s.replace(amp, "&")
    return s 

补充:我增加了对十六进制代码的匹配。我已经使用这个一段时间了,最近遇到了第一个情况,就是单引号/撇号(')。

2

ASCII是美国信息交换标准代码,它包含任何带重音的字母。如果你可以使用Unicode,那就最好了,建议你把它编码成UTF-8(如果你遇到一些编码特别糟糕的用户代理/客户端,可能需要用ISO-8859-1或者其他奇怪的编码方式,真让人无奈)。在那部分的内容类型头中,配合text/plain可以告诉别人你选择了什么编码方式。我建议你尽量使用UTF-8,除非你能明确证明它无法工作——现在几乎所有地方都支持UTF-8,而且它比任何ISO-8859或“代码页”的解决方案灵活得多!

撰写回答