我试图使用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上?
答案 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)
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
。