不是" \ u":如何在JSON中Unescape Unicode?

时间:2016-05-11 15:11:40

标签: python json unicode encoding scrapy

我试图使用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上?

2 个答案:

答案 0 :(得分:4)

修改(2016-10-19):

使用Scrapy 1.2+,您可以将FEED_EXPORT_ENCODING集用于输出JSON文件所需的字符编码,例如FEED_EXPORT_ENCODING = 'utf-8'(默认值为None,这意味着{ {1}}逃避)

注意:我正在调整what I wrote on GitHub for a similar issue我在问题评论中链接的内容。

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

Scrapy's default JSON exporter使用(默认)\uXXXX参数,因此在写入文件之前,它会将Unicode字符输出为ensure_ascii=True个序列。 (这是在执行\uXXXX

时使用的

在导出器中设置-o somefile.json将输出Unicode字符串which will end up as UTF-8 encoded on file。请参阅底部的自定义导出器代码。

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

ensure_ascii=False

带有>>> 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'} 序列的输入是Python的有效JSON(应该如此),\uXXXX生成有效的Python loads()

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

dict

现在使用>>> # 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"}'
>>>

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

1 ..定义自定义项目导出器,例如在项目的>>> 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型 白 送料込"} 文件中

exporters.py

2 ..替换$ 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)

中的默认JSON项目导出器
settings.py

答案 1 :(得分:1)

the codecs module使用text -> text decoding(在Python 2中,它不是绝对必要的,但在Python 3 str中没有decode方法,因为这些方法适用于str - > bytes并且返回,而不是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