将 HTML 实体转换为 Unicode,反之亦然

如何在 Python 中将 HTML 实体转换为 Unicode,反之亦然?

89751 次浏览

你需要 美味汤

from BeautifulSoup import BeautifulStoneSoup
import cgi


def HTMLEntitiesToUnicode(text):
"""Converts HTML entities to unicode.  For example '&' becomes '&'."""
text = unicode(BeautifulStoneSoup(text, convertEntities=BeautifulStoneSoup.ALL_ENTITIES))
return text


def unicodeToHTMLEntities(text):
"""Converts unicode to HTML entities.  For example '&' becomes '&'."""
text = cgi.escape(text).encode('ascii', 'xmlcharrefreplace')
return text


text = "&, ®, <, >, ¢, £, ¥, €, §, ©"


uni = HTMLEntitiesToUnicode(text)
htmlent = unicodeToHTMLEntities(uni)


print uni
print htmlent
# &, ®, <, >, ¢, £, ¥, €, §, ©
# &amp;, &#174;, &lt;, &gt;, &#162;, &#163;, &#165;, &#8364;, &#167;, &#169;

至于“反之亦然”(我需要我自己,导致我发现这个问题,这没有帮助,随后 另一个有答案的网站) :

u'some string'.encode('ascii', 'xmlcharrefreplace')

将返回一个包含任何转换为 XML (HTML)实体的非 ascii 字符的普通字符串。

正如 Hekevintran的答案所示,您可以使用 cgi.escape(s)来编码字符串,但是请注意,在该函数中,引号的编码默认为 false,因此在字符串旁边传递 quote=True关键字参数可能是一个好主意。但是,即使通过传递 quote=True,函数也不会转义单引号("'")(因为这些问题,函数自3.2版以来一直是 不赞成)

有人建议使用 html.escape(s)而不是 cgi.escape(s)

html.unescape(s)也是 在3.4版本中引入

所以在 python 3.4中,你可以:

  • 使用 html.escape(text).encode('ascii', 'xmlcharrefreplace').decode()将特殊字符转换为 HTML 实体。
  • html.unescape(text),用于将 HTML 实体转换回纯文本表示形式。

Python 2.7和 BeautifulSoup4的更新

Unescape ——使用 htmlparser(Python 2.7标准库)将 Unicode HTML 转换为 Unicode:

>>> escaped = u'Monsieur le Cur&eacute; of the &laquo;Notre-Dame-de-Gr&acirc;ce&raquo; neighborhood'
>>> from HTMLParser import HTMLParser
>>> htmlparser = HTMLParser()
>>> unescaped = htmlparser.unescape(escaped)
>>> unescaped
u'Monsieur le Cur\xe9 of the \xabNotre-Dame-de-Gr\xe2ce\xbb neighborhood'
>>> print unescaped
Monsieur le Curé of the «Notre-Dame-de-Grâce» neighborhood

Unescape ——将 HTML Unicode 转换为具有 bs4的 Unicode (BeautifulSoup4) :

>>> html = '''<p>Monsieur le Cur&eacute; of the &laquo;Notre-Dame-de-Gr&acirc;ce&raquo; neighborhood</p>'''
>>> from bs4 import BeautifulSoup
>>> soup = BeautifulSoup(html)
>>> soup.text
u'Monsieur le Cur\xe9 of the \xabNotre-Dame-de-Gr\xe2ce\xbb neighborhood'
>>> print soup.text
Monsieur le Curé of the «Notre-Dame-de-Grâce» neighborhood

转义——使用 bs4(BeautifulSoup4)将 Unicode 转换为 Unicode HTML:

>>> unescaped = u'Monsieur le Curé of the «Notre-Dame-de-Grâce» neighborhood'
>>> from bs4.dammit import EntitySubstitution
>>> escaper = EntitySubstitution()
>>> escaped = escaper.substitute_html(unescaped)
>>> escaped
u'Monsieur le Cur&eacute; of the &laquo;Notre-Dame-de-Gr&acirc;ce&raquo; neighborhood'

我使用以下函数将 xls 文件中的 unicode 转换为 html 文件,同时保留 xls 文件中的特殊字符:

def html_wr(f, dat):
''' write dat to file f as html
. file is assumed to be opened in binary format
. if dat is nul it is replaced with non breakable space
. non-ascii characters are translated to xml
'''
if not dat:
dat = '&nbsp;'
try:
f.write(dat.encode('ascii'))
except:
f.write(html.escape(dat).encode('ascii', 'xmlcharrefreplace'))

希望这对某人有用

如果有人像我一样想知道为什么一些实体编号(代码)像 &#153; (for trademark symbol), &#128; (for euro symbol)没有正确编码,原因是在 ISO-8859-1(又名 Windows-1252)这些字符没有定义。

还要注意,html5的默认字符集是 utf-8,html4的默认字符集是 ISO-8859-1

因此,我们将不得不想办法解决(首先找到并替换它们)

Mozilla 文档中的参考(起点)

Https://developer.mozilla.org/en-us/docs/web/guide/localizations_and_character_encodings

$ python3 -c "
> import html
> print(
>     html.unescape('&amp;&#169;&#x2014;')
> )"
&©—


$ python3 -c "
> import html
> print(
>     html.escape('&©—')
> )"
&amp;©—


$ python2 -c "
> from HTMLParser import HTMLParser
> print(
>     HTMLParser().unescape('&amp;&#169;&#x2014;')
> )"
&©—


$ python2 -c "
> import cgi
> print(
>     cgi.escape('&©—')
> )"
&amp;©—

HTML 只严格要求转义 &(与号)和 <(左尖括号/小于号)

#!/usr/bin/env python3
import fileinput
import html


for line in fileinput.input():
print(html.unescape(line.rstrip('\n')))

对于 python3使用 html.unescape():

import html
s = "&amp;"
decoded = html.unescape(s)
# &