I'm trying to decode HTML entries from here NYTimes.com and I cannot figure out what I am doing wrong.
Take for example:
"U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’"
I've tried BeautifulSoup, decode('iso-8859-1'), and django.utils.encoding's smart_str without any success.
4 Answers 4
>>> from HTMLParser import HTMLParser
>>> print HTMLParser().unescape('U.S. Adviser’s Blunt Memo on Iraq: '
... 'Time ‘to Go Home’')
U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’
The function is undocumented in Python 2. It is fixed in Python 3.4+: it is exposed as html.unescape() there.
1 Comment
Actually what you have are not HTML entities. There are THREE varieties of those &.....; thingies -- for example     all mean U+00A0 NO-BREAK SPACE.
  (the type you have) is a "numeric character reference" (decimal).
  is a "numeric character reference" (hexadecimal).
is an entity.
Further reading: http://htmlhelp.com/reference/html40/entities/
Here you will find code for Python2.x that does all three in one scan through the input: http://effbot.org/zone/re-sub.htm#unescape-html
Comments
This does work:
from BeautifulSoup import BeautifulStoneSoup
s = "U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’"
decoded = BeautifulStoneSoup(s, convertEntities=BeautifulStoneSoup.HTML_ENTITIES)
If you want a string instead of a Unicode object, you'll need to decode it to an encoding that supports the characters being used; ISO-8859-1 doesn't:
result = decoded.encode("UTF-8")
It's unfortunate that you need an external module for something like this; simple HTML/XML entity decoding should be in the standard library, and not require me to use a library with meaningless class names like "BeautifulStoneSoup". (Class and function names should not be "creative", they should be meaningful.)
5 Comments
Try this:
import re
def _callback(matches):
id = matches.group(1)
try:
return unichr(int(id))
except:
return id
def decode_unicode_references(data):
return re.sub("&#(\d+)(;|(?=\s))", _callback, data)
data = "U.S. Adviser’s Blunt Memo on Iraq: Time ‘to Go Home’"
print decode_unicode_references(data)
5 Comments
  and but then it will crash in int() (2) Allowing the character reference (it's NOT an entity) to end in a whitespace instead of ';' seems very tolerant -- shouldn't you mention this? (3) Wouldn't the last part be better written as [;\s]?&#, but yes it should have been \d. Regarding point two to allowing it to end with whitespace, it should be noted that even though it isn't pretty, it's still supported. I've updated the code in the following way: (1) Changed it to \d, (2) made the callback a bit stronger, and (3) used a lookahead assertion for ending whitespace instead of absorbing it like it was.& instead of ; all gave the same result: they terminate the reference and are not swallowed. I'm looking forward to your updated solution ;-)Explore related questions
See similar questions with these tags.
unescape().