2011-01-26 3 views
4

Это смешно .. Я пытаюсь читать данные географического поиска из openstreetmap. Код, который выполняет запрос выглядит следующим образомпроблема с декодированием unicode

params = urllib.urlencode({'q': ",".join([e for e in full_address]), 'format': "json", "addressdetails" : "1"}) 
query = "http://nominatim.openstreetmap.org/search?%s" % params 
print query 
time.sleep(5) 
response = json.loads(unicode(urllib.urlopen(query).read(), "UTF-8"), encoding="UTF-8") 
print response 

запрос для Zürich правильно URL-закодированных данных в UTF-8. Здесь нет чудес.

http://nominatim.openstreetmap.org/search?q=Z%C3%BCrich%2CSWITZERLAND&addressdetails=1&format=json 

При печати ответа, то у с умляутом кодируются latin1 (0xFC)

[{u'display_name': u'Z\xfcrich, Bezirk Z\xfcrich, Z\xfcrich, Schweiz, Europe', u'place_id': 588094, u'lon': 8.540443 

но это нонсенс, потому что OpenStreetMap возвращает данные JSON в UTF-8

Connecting to nominatim.openstreetmap.org (nominatim.openstreetmap.org)|128.40.168.106|:80... connected. 
HTTP request sent, awaiting response... 
    HTTP/1.1 200 OK 
    Date: Wed, 26 Jan 2011 13:48:33 GMT 
    Server: Apache/2.2.14 (Ubuntu) 
    Content-Location: search.php 
    Vary: negotiate 
    TCN: choice 
    X-Powered-By: PHP/5.3.2-1ubuntu4.7 
    Access-Control-Allow-Origin: * 
    Content-Length: 3342 
    Keep-Alive: timeout=15, max=100 
    Connection: Keep-Alive 
    Content-Type: application/json; charset=UTF-8 
Length: 3342 (3.3K) [application/json] 

что также подтверждается содержимым файла, а затем я прямо говорю, что это UTF-8 как при чтении, так и в json-синтаксическом анализе.

Что здесь происходит?

EDIT: По-видимому, это json.loads, который как-то завинчивается.

ответ

8

Когда я иду и напечатать ответ, у с умляутом кодируется latin1 (0xFC)

Вы просто искажая выход. Это строка в Юникоде (вы можете указать в префиксе u), нет кодировки «прикреплено» - это означает, что \ xFC означает, что это код с номером 0xFC, который, как представляется, является U-Umlaut (см. http://www.fileformat.info/info/unicode/char/fc/index.htm). Причина этого в том, что нумерация первых 256 кодов Unicode совпадает с латинской кодировкой.

Короче говоря, вы сделали все правильно - у вас есть объект unicode с нужным контентом (который не агностик для кодирования), вы можете выбрать кодировку, которую хотите, когда используете этот контент для вывода где-то, выполнив unicodestr.encode («utf-8») или с использованием кодеков, см. http://docs.python.org/howto/unicode.html#reading-and-writing-unicode-data

+0

@etarion, но он говорит 'UTF-8 (HEX) 0xC3 0xBC' в таблице. Разве он не должен быть представлен как таковой в содержании UTF-8? Если я не ошибаюсь, если я принимаю 'oxFC' буквально и использую его как символ в строке UTF-8, это будет недопустимый символ. –

+0

Возможно, вы правы ... Как я могу проверить, является ли это кодовым или фактическим данным? попытаться декодировать его на ascii? –

+0

+1: Я думал, что это может быть что-то подобное, но мой python-fu недостаточно высок, чтобы проверить его правильно. запись 'print u'Z \ xfcrich'' в консоли UTF8 напечатала правильную вещь, в конце концов. – araqnid

1

Выход прекрасен. Всякий раз, когда вы печатаете данные на консоли, Python учитывает Unicode данные только при печати фактической строки. Если напечатать список юникоды, каждая строка Юникода показать на консоли, как его предст():

>>> a=u'á' 
>>> a 
u'\xe1' 
>>> print a 
á 
>>> [a] 
[u'\xe1'] 
>>> print [a] 
[u'\xe1']