2013-08-08 16 views
2

Я создаю подключение к API Google Finance, который дает мне котировки акций. Все работает нормально, пока я не перейду на курсы из Европы. Они содержат символ «Европа», и я получаю следующую ошибку:UnicodeDecodeError: кодек «utf8» не может декодировать байт - символ евро

Traceback (most recent call last): 
    File "C:\Users\Administrator\Desktop\getQuotes.py", line 32, in <module> 
    quote = c.get("SAP","FRA") 
    File "C:\Users\Administrator\Desktop\getQuotes.py", line 21, in get 
    obj = json.loads(content[3:]) 
    File "C:\Python27\lib\json\__init__.py", line 338, in loads 
    return _default_decoder.decode(s) 
    File "C:\Python27\lib\json\decoder.py", line 365, in decode 
    obj, end = self.raw_decode(s, idx=_w(s, 0).end()) 
    File "C:\Python27\lib\json\decoder.py", line 381, in raw_decode 
    obj, end = self.scan_once(s, idx) 
UnicodeDecodeError: 'utf8' codec can't decode byte 0x80 in position 0: invalid start byte 

Следующий код, который я использую. Я думаю, что ошибка появляется в то время как JSON пытается обработки строки, но он не может разрешить символ евро:

import urllib2 
import json 
import time 

class GoogleFinanceAPI: 
    def __init__(self): 
     self.prefix = "http://finance.google.com/finance/info?client=ig&q=" 

    def get(self,symbol,exchange): 
     url = self.prefix+"%s:%s"%(exchange,symbol) 
     u = urllib2.urlopen(url) 
     content = u.read() 

     obj = json.loads(content[3:]) 
     return obj[0] 


if __name__ == "__main__": 
    c = GoogleFinanceAPI() 

    while 1: 
     quote = c.get("MSFT","NASDAQ") 
     print quote 
     time.sleep(30) 

Это как Google Finance дает мне выход для SAP запаса, содержащего символ евро:

// [ { "id": "8424920" ,"t" : "SAP" ,"e" : "FRA" ,"l" : "56.51" ,"l_cur" : "€56.51" ,"s": "0" ,"ltt":"8:00PM GMT+2" ,"lt" : "Aug 7, 8:00PM GMT+2" ,"c" : "-0.47" ,"cp" : "-0.82" ,"ccol" : "chr" } ] 

Я пытался использовать эту функцию, и вместо того, чтобы нож (содержание [3:]) часть, но с этим я получил ту же ошибку, и что вместо UTF-8 я получил сообщение об ошибке ASCII.

json.loads(unicode(opener.open(...), "ISO-8859-15")) 

Если у кого-то есть идея, я был бы очень доволен.

+0

интересно, что ресурсы возвращает 'кодовую = ISO-8859-1'. Ясно, что ложь. Он даже «удостаивает» заголовок запроса «Accept-Charset», но это не влияет на объект ответа, это «0x80», независимо от того, какая кодировка заголовков настаивает на том, что это должно быть. Я бы рассматривал это как ошибку в службе finance.google.com – SingleNegationElimination

ответ

3

Документ, который вы извлекаете, как представляется, закодирован с помощью Windows Codepage 1252, где символ знака евро кодируется как \x80. Это недопустимый байт в UTF-8 и непечатный управляющий символ во всех вариантах ISO-8859. Попробуйте:

obj = json.loads(content[3:], 'cp1252') 
+0

Спасибо! Это решило мою проблему. Иногда эти кодировки довольно жесткие. – Max

2

По какой-то причине API Google Finance возвращает данные страницы 1252. Вы можете узнать, что это было сделано так, что я смотрел на Content-Type заголовок:

>>> u= urllib2.urlopen('http://finance.google.com/finance/info?client=ig&q=SAP:FRA') 
>>> u.headers['Content-Type'] 
'text/html; charset=ISO-8859-1' 

text/html мире, ISO-8859-1 действительно означает код страницы Windows 1252, для утомительных исторических причин Есть несколько. . другие для различных локалей Бог знает, почему Google возвращается text/html для того, что явно не HTML ресурса, хотя ум ...)

Но вы действительно не хотите кодовой страницы 1252, даже если вы можете расшифровать его с помощью json.loads(..., 'windows-1252') - это странная кодировка для JSON, и кто знает, что произойдет с другими символами валюты, недоступными в этой кодировке.

Если я просматриваю один и тот же URL-адрес в браузере, я получаю правильный результат UTF-8. Зачем? Похоже, что Google - нюхание UA. Установить заголовок UA, чтобы получить нужную кодировку:

>>> u= urllib2.urlopen('http://finance.google.com/finance/info?client=ig&q=SAP:FRA', headers= {'User-Agent': 'Mozilla/5.0'}) 
>>> u.headers['Content-Type'] 
'text/html; charset=UTF-8' 

BAD GOOGLE

Смежные вопросы