繁体   English   中英

不是“\ u”:如何在JSON中使用Unicode?

[英]Not “\u”: How to Unescape Unicode in JSON?

我正在尝试使用Scrapy从非英语网站上搜集。 作为JSON的刮擦结果看起来像这样:

{"price": "13,000", "name": "\u58c1\u6bb4\u308a\u4ee3\u884c\u69d8\u5c02\u7528\u2605 \u30c6\u30ec\u30d3\u672c\u4f53 20v\u578b \u767d \u9001\u6599\u8fbc"},

这是我正在使用的代码:

def parse(self, response):
    for sel in response.xpath('//section[@class="items-box"]'):
      item = ShopItem()
      item['name'] = sel.xpath('a/div/h3/text()').extract()
      item['price'] = sel.xpath('a/div/div/div[1]/text()').extract().replace("$", "")
      yield item

如何将未转义的Unicode字符输出到JSON上?

编辑 (2016-10-19):

使用Scrapy 1.2+,您可以将FEED_EXPORT_ENCODING设置为输出JSON文件所需的字符编码,例如FEED_EXPORT_ENCODING = 'utf-8' (默认值为None ,表示\\uXXXX转义)


注意:我正在调整我在GitHub上写的内容,以解决我在问题评论中链接的类似问题

请注意,Scrapy上存在一个未解决的问题,即使输出编码为参数: https//github.com/scrapy/scrapy/issues/1965


Scrapy的默认JSON导出器使用(默认值) ensure_ascii=True参数,因此在写入文件之前将Unicode字符输出为\\uXXXX序列。 (这是做-o somefile.json

在导出器中设置ensure_ascii=False将输出Unicode字符串, 最终将在文件上以UTF-8编码 请在此处查看底部的自定义导出器代码。

为了说明,让我们将您的输入JSON字符串读回一些数据以进行处理:

>>> import json
>>> test = r'''{"price": "13,000", "name": "\u58c1\u6bb4\u308a\u4ee3\u884c\u69d8\u5c02\u7528\u2605 \u30c6\u30ec\u30d3\u672c\u4f53 20v\u578b \u767d \u9001\u6599\u8fbc"}'''
>>> json.loads(test)
{u'price': u'13,000', u'name': u'\u58c1\u6bb4\u308a\u4ee3\u884c\u69d8\u5c02\u7528\u2605 \u30c6\u30ec\u30d3\u672c\u4f53 20v\u578b \u767d \u9001\u6599\u8fbc'}

带有\\uXXXX序列的输入是Python的有效JSON(应该如此),而loads()生成一个有效的Python dict

现在让我们再次序列化为JSON:

>>> # dumping the dict back to JSON, with default ensure_ascii=True
>>> json.dumps(json.loads(test))
'{"price": "13,000", "name": "\\u58c1\\u6bb4\\u308a\\u4ee3\\u884c\\u69d8\\u5c02\\u7528\\u2605 \\u30c6\\u30ec\\u30d3\\u672c\\u4f53 20v\\u578b \\u767d \\u9001\\u6599\\u8fbc"}'
>>> 

现在有了ensure_ascii=False

>>> # now dumping with ensure_ascii=False, you get a Unicode string
>>> json.dumps(json.loads(test), ensure_ascii=False)
u'{"price": "13,000", "name": "\u58c1\u6bb4\u308a\u4ee3\u884c\u69d8\u5c02\u7528\u2605 \u30c6\u30ec\u30d3\u672c\u4f53 20v\u578b \u767d \u9001\u6599\u8fbc"}'
>>>

让我们打印看看差异:

>>> print json.dumps(json.loads(test))
{"price": "13,000", "name": "\u58c1\u6bb4\u308a\u4ee3\u884c\u69d8\u5c02\u7528\u2605 \u30c6\u30ec\u30d3\u672c\u4f53 20v\u578b \u767d \u9001\u6599\u8fbc"}

>>> print json.dumps(json.loads(test), ensure_ascii=False)
{"price": "13,000", "name": "壁殴り代行様専用★ テレビ本体 20v型 白 送料込"}

如果你想把JSON项目写成UTF-8,你可以这样做:

1 ..定义自定义项目导出器,例如在项目的exporters.py文件中

$ cat myproject/exporters.py 
from scrapy.exporters import JsonItemExporter


class Utf8JsonItemExporter(JsonItemExporter):

    def __init__(self, file, **kwargs):
        super(Utf8JsonItemExporter, self).__init__(
            file, ensure_ascii=False, **kwargs)

2 ..替换settings.py的默认JSON项目导出器

FEED_EXPORTERS = {
    'json': 'myproject.exporters.Utf8JsonItemExporter',
}

使用codecs模块进行文本 - >文本解码 (在Python 2中它并不是绝对必要的,但在Python 3中str没有decode方法,因为这些方法适用于str - > bytes和back,而不是str - > str ) 。 使用unicode_escape编解码器进行解码将获得正确的数据:

import codecs

somestr = codecs.decode(strwithescapes, 'unicode-escape')

所以要修复你得到的名字,你会做:

item['name'] = codecs.decode(sel.xpath('a/div/h3/text()').extract(), 'unicode-escape')

如果问题出在您正在生成的JSON中,您只需要确保json模块不强制字符串为带字符编码的ASCII; 它默认情况下是这样做的,因为并非所有JSON解析器都能处理真正的Unicode字符(它们通常假设数据以带有转义的ASCII字节发送)。 因此,无论您何时调用json.dump / json.dumps (或创建json.JSONEncoder ),请确保显式传递ensure_ascii=False

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM