2

我建立了与 Google Finance API 的连接,它为我提供股票报价。一切都很好,直到我从欧洲转学。这些包含€符号,我收到以下错误:

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" } ]

我尝试使用这个函数,而不是打开器的 (content[3:]) 部分,但是我得到了同样的错误,而且我得到了一个 ascii 错误,而不是 utf-8。

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

如果有人有想法,我会很高兴。

4

2 回答 2

3

您正在获取的文档似乎使用 Windows 代码页 1252 进行编码,其中欧元符号字符编码为\x80. 这是 UTF-8 中的无效字节和所有 ISO-8859 变体中的非打印控制字符。尝试:

obj = json.loads(content[3:], 'cp1252')
于 2013-08-08T01:45:42.813 回答
2

出于某种原因,Google Finance API 正在返回代码页 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,由于繁琐的历史原因。还有其他一些用于不同的语言环境。天知道为什么谷歌要返回text/html显然不是 HTML 资源的东西…… )

但是你并不真正想要代码页 1252,即使你可以使用它来解码它json.loads(..., 'windows-1252')——它是 JSON 的一种奇怪的编码,谁知道该编码中不可用的其他货币符号会发生什么。

如果我在浏览器中查看相同的 URL,我会得到正确的 UTF-8 结果。为什么?似乎谷歌正在嗅探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'

坏谷歌

于 2013-08-08T16:28:56.027 回答