2

我试图解析来自谷歌天气 api 的响应,但我得到这个格式不正确的错误,据我所知,响应格式正确。

以下是相关代码:

f = urllib.urlopen(WEATHERPATH + sys.argv[1])
parser = make_parser()
parser.setContentHandler(GoogleWeatherHandler())
parser.parse(f)

XML:

<?xml version="1.0"?>
<xml_api_reply version="1">
    <weather module_id="0" tab_id="0" mobile_row="0" mobile_zipped="1" row="0" section="0" >
        <forecast_information>
            <city data="Ciudad Ju�rez, Chihuahua"/><postal_code data="Juarez"/>
            <latitude_e6 data=""/>
            <longitude_e6 data=""/>
            <forecast_date data="2012-08-14"/>
            <current_date_time data="2012-08-15 02:51:00 +0000"/>
            <unit_system data="US"/></forecast_information>
            <current_conditions>
                <condition data="Cloudy"/>
                <temp_f data="91"/>
                <temp_c data="33"/>
                <humidity data="Humidity: 22%"/>
                <icon data="/ig/images/weather/cloudy.gif"/>
                <wind_condition data="Wind: SE at 6 mph"/>
            </current_conditions>
                        // similar markup
</weather>
</xml_api_reply>

和错误:

Traceback (most recent call last):
  File "weather.py", line 34, in <module>
    main()
  File "weather.py", line 30, in main
    parser.parse(f)
  File "c:\Python26\lib\xml\sax\expatreader.py", line 107, in parse
    xmlreader.IncrementalParser.parse(self, source)
  File "c:\Python26\lib\xml\sax\xmlreader.py", line 123, in parse
    self.feed(buffer)
  File "c:\Python26\lib\xml\sax\expatreader.py", line 211, in feed
    self._err_handler.fatalError(exc)
  File "c:\Python26\lib\xml\sax\handler.py", line 38, in fatalError
    raise exception
xml.sax._exceptions.SAXParseException: <unknown>:1:179: not well-formed (invalid
 token)

所有导入都已经到位,我相信解释器,但我在 xml 上找不到错误,第二:知道什么<unknown>:1:179意思会很有效。

谢谢。

4

1 回答 1

3

看起来重音á字符Juárez是问题所在。你还没有告诉解析器编码是什么,所以它显然是默认的,可能是 UTF-8,其中那个字符值是无效的——即它期待 UTF-8 编码,而你的实际编码可能是 ISO-8859- 1.

将解析器配置为期望 ISO-8859-1,您的问题应该会消失。

如果您可以修改 XML,请将标头更改为

<?xml version="1.0" encoding="iso-8859-1" ?>

Unicode 是定义字符集的标准,是对所有已知语言中每个可能的字符的唯一编号的抽象分配。

UTF-8 只是将这些字符编码为 8 位字节的几种可能方法之一。由于 UTF-8 必须编码超过 256 个字符,因此它使用 2、3 和 4 字节序列。为避免歧义,这些序列必须以其他方式无法使用的字符开头,因此保留一组高阶位模式(以及因此的某些字节值集)来标记这些多字节序列的开始。ISO-8859-1 中使用的编码(一种不同的字符编码方式)á恰好与 UTF-8 中保留的用于标记多字节序列的字符冲突。

对这些问题的部分混淆源于这样一个事实:对于 0x20 到 0x7f 的字符代码,所有不同的编码方法都是相同的(单个字节)以实现向后兼容性。当您冒险使用不属于标准 ASCII 的字符时,情况会因编码而异。

要更具体:

Unicode á   - 0x00E1 
ISO-8859-1  - 0xE1
UTF-8       - 0xc3 0xa1

这里发生的情况是,历史上(在 Unicode 之前)á已经在各种计算机标准(例如 Windows-1252)中分配了值 0xE1。当 Unicode 被设计出来时,他们保留了这个代码,但是当需要用 UTF-8编码这个值时,规则指定它变成一个 2 字节序列 0xc3 0xa1。UTF-8 中不允许单个字符值 0xE1 单独出现(我相信它标志着 4 字节序列的开始,但我可能弄错了)。

于 2012-08-15T05:44:44.747 回答