ric*_*row 4 python unicode encoding json 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"},
Run Code Online (Sandbox Code Playgroud)
这是我正在使用的代码:
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
Run Code Online (Sandbox Code Playgroud)
我如何将未转义的 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参数,因此它\uXXXX在写入文件之前将Unicode 字符作为序列输出。(这是做的时候用的-o somefile.json)
ensure_ascii=False导出器中的设置将输出 Unicode 字符串,最终将在 file 上编码为 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'}
Run Code Online (Sandbox Code Playgroud)
带有\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"}'
>>>
Run Code Online (Sandbox Code Playgroud)
现在有了 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"}'
>>>
Run Code Online (Sandbox Code Playgroud)
让我们打印以查看差异:
>>> 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? ? ???"}
Run Code Online (Sandbox Code Playgroud)
如果您想将 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)
Run Code Online (Sandbox Code Playgroud)
2.. 替换您的默认 JSON 项目导出器 settings.py
FEED_EXPORTERS = {
'json': 'myproject.exporters.Utf8JsonItemExporter',
}
Run Code Online (Sandbox Code Playgroud)
使用该codecs模块进行文本 -> 文本解码(在 Python 2 中这不是绝对必要的,但在 Python 3 中str没有decode方法,因为这些方法是 for str->bytes和 back,而不是str-> str)。使用unicode_escape编解码器进行解码将为您返回正确的数据:
import codecs
somestr = codecs.decode(strwithescapes, 'unicode-escape')
Run Code Online (Sandbox Code Playgroud)
因此,要修复您获得的名称,您需要执行以下操作:
item['name'] = codecs.decode(sel.xpath('a/div/h3/text()').extract(), 'unicode-escape')
Run Code Online (Sandbox Code Playgroud)
如果问题出在您正在生成的 JSON 中,您只需确保该json模块不会强制字符串为带有字符编码的 ASCII;它默认这样做是因为并非所有 JSON 解析器都可以处理真正的 Unicode 字符(它们通常假设数据作为带转义的 ASCII 字节发送)。因此,无论您在哪里调用json.dump/ json.dumps(或创建json.JSONEncoder),请确保显式传递ensure_ascii=False。
| 归档时间: |
|
| 查看次数: |
3005 次 |
| 最近记录: |