Html character entity conversion
Claudio Grondi
claudio.grondi at freenet.de
Mon Jul 31 02:47:48 EDT 2006
John Machin wrote:
> Claudio Grondi wrote:
>
>>pak.andrei at gmail.com wrote:
>>
>>>Claudio Grondi wrote:
>>>
>>>
>>>>pak.andrei at gmail.com wrote:
>>>>
>>>>
>>>>>Here is my script:
>>>>>
>>>>
>>>>>from mechanize import *
>>>>>from BeautifulSoup import *
>>>>
>>>>>import StringIO
>>>>>b = Browser()
>>>>>f = b.open("http://www.translate.ru/text.asp?lang=ru")
>>>>>b.select_form(nr=0)
>>>>>b["source"] = "hello python"
>>>>>html = b.submit().get_data()
>>>>>soup = BeautifulSoup(html)
>>>>>print soup.find("span", id = "r_text").string
>>>>>
>>>>>OUTPUT:
>>>>>привет
>>>>>питон
>>>>>----------
>>>>>In russian it looks like:
>>>>>"привет питон"
>>>>>
>>>>>How can I translate this using standard Python libraries??
>>>>>
>>>>>--
>>>>>Pak Andrei, http://paxoblog.blogspot.com, icq://97449800
>>>>>
>>>>
>>>>Translate to what and with what purpose?
>>>>
>>>>Assuming your intention is to get a Python Unicode string, what about:
>>>>
>>>>strHTML = 'привет
>>>>питон'
>>>>strUnicodeHexCode = strHTML.replace('&#','\u').replace(';','')
>>>>strUnicode = eval("u'%s'"%strUnicodeHexCode)
>>>>
>>>>?
>>>>
>>>>I am sure, there is a more elegant and direct solution, but just wanted
>>>>to provide here some quick response.
>>>>
>>>>Claudio Grondi
>>>
>>>
>>>Thank you, Claudio.
>>>Really interest solution, but it doesn't work...
>>>
>>>In [19]: strHTML = 'привет
>>>питон'
>>>
>>>In [20]: strUnicodeHexCode = strHTML.replace('&#','\u').replace(';','')
>>>
>>>In [21]: strUnicode = eval("u'%s'"%strUnicodeHexCode)
>>>
>>>In [22]: print strUnicode
>>>---------------------------------------------------------------------------
>>>exceptions.UnicodeEncodeError Traceback (most
>>>recent call last)
>>>
>>>C:\Documents and Settings\dron\<ipython console>
>>>
>>>C:\usr\lib\encodings\cp866.py in encode(self, input, errors)
>>> 16 def encode(self,input,errors='strict'):
>>> 17
>>>---> 18 return codecs.charmap_encode(input,errors,encoding_map)
>>> 19
>>> 20 def decode(self,input,errors='strict'):
>>>
>>>UnicodeEncodeError: 'charmap' codec can't encode characters in position
>>>0-5: character maps to <undefined>
>>>
>>>In [23]: print strUnicode.encode("utf-8")
>>>сВЗсВИсВАсБ┤сБ╖сВР сВЗсВАсВРсВЖсВЕ
>>><-- it's not my string "привет питон"
>>>
>>>In [24]: strUnicode.encode("utf-8")
>>>Out[24]:
>>>'\xe1\x82\x87\xe1\x82\x88\xe1\x82\x80\xe1\x81\xb4\xe1\x81\xb7\xe1\x82\x90
>>>\xe1\x82\x87\xe1\x82\x80\xe1\x82\x90\xe1\x82\x86\xe1\x82\
>>>x85' <-- and too many chars
>>>
>>
>>Have you considered, that the HTML page specifies charset=windows-1251
>>in its
>><meta http-equiv="Content-Type" content="text/html;
>>charset=windows-1251"> tag ?
>>You are apparently on Linux or so, so I can't track this problem down
>>having only a Windows box here, but inbetween I know that there is
>>another problem with it:
>>I have erronously assumed, that the numbers in п are hexadecimal,
>>but they are decimal, so it is necessary to do hex(int('1087')) on them
>>to get at the right code to put into eval().
>>As you know now the idea I hope you will succeed as I did with:
>>
>> >>> lstIntUnicodeDecimalCode = strHTML.replace('&#','').split(';')
>> >>> lstIntUnicodeDecimalCode
>>['1087', '1088', '1080', '1074', '1077', '1090', ' 1087', '1080',
>>'1090', '1086', '1085', '']
>> >>> lstIntUnicodeDecimalCode = lstIntUnicodeDecimalCode[:-1]
>> >>> lstHexUnicode = [ hex(int(item)) for item in lstIntUnicodeDecimalCode]
>> >>> lstHexUnicode
>>['0x43f', '0x440', '0x438', '0x432', '0x435', '0x442', '0x43f', '0x438',
>>'0x442', '0x43e', '0x43d']
>> >>> eval( 'u"%s"'%''.join(lstHexUnicode).replace('0x','\u0' ) )
>>u'\u043f\u0440\u0438\u0432\u0435\u0442\u043f\u0438\u0442\u043e\u043d'
>> >>> strUnicode = eval(
>>'u"%s"'%''.join(lstHexUnicode).replace('0x','\u0' ) )
>> >>> print strUnicode
>>приветпитон
>>
>>Sorry for that mess not taking the space into consideration, but I think
>> you can get the idea anyway.
>
>
> I hope he *doesn't* get that "idea".
>
> #>>> strHTML =
> 'приветпит&#
> 1086;н'
> #>>> strUnicode = [unichr(int(x)) for x in
> strHTML.replace('&#','').split(';') if
> x]
> #>>> strUnicode
> [u'\u043f', u'\u0440', u'\u0438', u'\u0432', u'\u0435', u'\u0442',
> u'\u043f', u'
> \u0438', u'\u0442', u'\u043e', u'\u043d']
> #>>>
Knowing about the built-in function unichr() is a good thing, but ...
there are still drawbacks, because (not tested!) e.g. :
'100x hallo Python' translates to
'100x привет
Питон'
and can't be handled by improving the core idea by usage of unichr()
instead of the eval() stuff because of the wrong approach with using
.replace() and .split() which work only on the given example but not in
general case.
I am just too lazy to sit down and work on code extracting from the HTML
the &#....; sequences to convert only them letting the other content of
the string unchanged in order to arrive at a solution that works in
general case (it should be not hard and I suppose the OP has it already
:-) if he is at a Python skill level of playing around with the
mechanize module).
I am still convinced, that there must be a more elegant and direct
solution, so the subject is still fully open for improvements towards
the actual final goal.
I suppose, that one can use in addition to unichr() also unicode() as
replacement for usage of eval().
To Andrei: can you please post here what you have finally arrived at?
Claudio Grondi
More information about the Python-list
mailing list