本问题已经有最佳答案,请猛点这里访问。
我正在做一些网页抓取工作,并且网站经常使用HTML实体来表示非ascii字符。 Python是否有一个实用程序可以接受带有HTML实体的字符串并返回unicode类型?
例如:
我回来了:
代表带有音调标记的"ǎ"。 以二进制形式表示为16位01ce。 我想将html实体转换为值u'\\u01ce'
Python具有htmlentitydefs模块,但是其中不包含对HTML实体进行转义的功能。
Python开发人员Fredrik Lundh(elementtree的作者等)在他的网站上具有这样的功能,该功能可用于十进制,十六进制和命名实体:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| import re, htmlentitydefs
##
# Removes HTML or XML character references and entities from a text string.
#
# @param text The HTML (or XML) source text.
# @return The plain text, as a Unicode string, if necessary.
def unescape(text):
def fixup(m):
text = m.group(0)
if text[:2] =="&#":
# character reference
try:
if text[:3] =="&#x":
return unichr(int(text[3:-1], 16))
else:
return unichr(int(text[2:-1]))
except ValueError:
pass
else:
# named entity
try:
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
except KeyError:
pass
return text # leave as is
return re.sub("", fixup, text) |
标准库自己的HTMLParser具有未记录的函数unescape(),它可以完全按照您的想法进行操作:
直至Python 3.4:
1 2 3 4
| import HTMLParser
h = HTMLParser.HTMLParser()
h.unescape('© 2010') # u'\\xa9 2010'
h.unescape(' 2010') # u'\\xa9 2010' |
Python 3.4+:
1 2 3
| import html
html.unescape('© 2010') # u'\\xa9 2010'
html.unescape(' 2010') # u'\\xa9 2010' |
使用内置的unichr-不需要BeautifulSoup:
1 2 3
| >>> entity = 'ǎ'
>>> unichr(int(entity[3:],16))
u'\\u01ce' |
如果您使用的是Python 3.4或更高版本,则可以简单地使用html.unescape:
1 2 3
| import html
s = html.unescape(s) |
替代方法,如果您有lxml:
1 2 3
| >>> import lxml.html
>>> lxml.html.fromstring('ǎ').text
u'\\u01ce' |
您可以在这里找到答案-从网页获取国际字符?
编辑:似乎BeautifulSoup不会转换以十六进制形式编写的实体。可以解决:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import copy, re
from BeautifulSoup import BeautifulSoup
hexentityMassage = copy.copy(BeautifulSoup.MARKUP_MASSAGE)
# replace hexadecimal character reference by decimal one
hexentityMassage += [(re.compile(' ]+);'),
lambda m: ' ' % int(m.group(1), 16))]
def convert(html):
return BeautifulSoup(html,
convertEntities=BeautifulSoup.HTML_ENTITIES,
markupMassage=hexentityMassage).contents[0].string
html = '<html> </html>'
print repr(convert(html))
# u'\\u01ce\\u01ce' |
编辑:
@dF提到的unescape()函数使用htmlentitydefs标准模块和unichr()在这种情况下可能更合适。
此功能应该可以帮助您正确处理并将实体转换回utf-8字符的功能。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| def unescape(text):
"""Removes HTML or XML character references
and entities from a text string.
@param text The HTML (or XML) source text.
@return The plain text, as a Unicode string, if necessary.
from Fredrik Lundh
2008-01-03: input only unicode characters string.
http://effbot.org/zone/re-sub.htm#unescape-html
"""
def fixup(m):
text = m.group(0)
if text[:2] =="&#":
# character reference
try:
if text[:3] =="&#x":
return unichr(int(text[3:-1], 16))
else:
return unichr(int(text[2:-1]))
except ValueError:
print"Value Error"
pass
else:
# named entity
# reescape the reserved characters.
try:
if text[1:-1] =="amp":
text ="&"
elif text[1:-1] =="gt":
text =">"
elif text[1:-1] =="lt":
text ="<"
else:
print text[1:-1]
text = unichr(htmlentitydefs.name2codepoint[text[1:-1]])
except KeyError:
print"keyerror"
pass
return text # leave as is
return re.sub("", fixup, text) |
不知道为什么堆栈溢出线程不包含';'在搜索/替换中(即lambda m:'em>; *'),否则,BeautifulSoup可能会倒钩,因为可以将相邻字符解释为HTML代码的一部分(即&#39B表示&#39Blackout)。
这对我来说更好:
1 2 3 4 5 6 7 8 9 10 11
| import re
from BeautifulSoup import BeautifulSoup
html_string=' Blackout in a can; on some shelves despite ban'
hexentityMassage = [(re.compile(' ]+);'),
lambda m: ' ' % int(m.group(1), 16))]
soup = BeautifulSoup(html_string,
convertEntities=BeautifulSoup.HTML_ENTITIES,
markupMassage=hexentityMassage) |
int(m.group(1),16)将数字(以base-16指定)格式转换回整数。
m.group(0)返回整个匹配项,m.group(1)返回正则表达式捕获组
基本上,使用markupMessage与:
html_string = re.sub('] +);',lambda m:''%int(m.group(1),16),html_string)
另一个解决方案是内置库xml.sax.saxutils(用于html和xml)。但是,它将仅转换&gt,&amp和&lt。
1 2 3
| from xml.sax.saxutils import unescape
escaped_text = unescape(text_to_escape) |
这是dF的答案的Python 3版本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import re
import html.entities
def unescape(text):
"""
Removes HTML or XML character references and entities from a text string.
:param text: The HTML (or XML) source text.
:return: The plain text, as a Unicode string, if necessary.
"""
def fixup(m):
text = m.group(0)
if text[:2] =="&#":
# character reference
try:
if text[:3] =="&#x":
return chr(int(text[3:-1], 16))
else:
return chr(int(text[2:-1]))
except ValueError:
pass
else:
# named entity
try:
text = chr(html.entities.name2codepoint[text[1:-1]])
except KeyError:
pass
return text # leave as is
return re.sub("", fixup, text) |
主要更改涉及现在为html.entities的htmlentitydefs和现在为chr的unichr。请参阅此Python 3移植指南。