Python 如何避免JSON百分比编码和\u转义?
当我解析文件时Python 如何避免JSON百分比编码和\u转义?,python,json,unicode,scrapy,Python,Json,Unicode,Scrapy,当我解析文件时 <html> <head><meta charset="UTF-8"></head> <body><a href="Düsseldorf.html">Düsseldorf</a></body> </html> 我以\u转义结束 [{ "name": "D\u00fcsseldorf", "url": "D\u00fcsseldorf.htm
<html>
<head><meta charset="UTF-8"></head>
<body><a href="Düsseldorf.html">Düsseldorf</a></body>
</html>
我以\u
转义结束
[{
"name": "D\u00fcsseldorf",
"url": "D\u00fcsseldorf.html"
}]
或使用百分比编码字符串
D%C3%BCsseldorf
描述的
以及相应的提要导出器设置
FEED_EXPORTERS = {
'json': 'myproj.exporter.UnicodeJsonLinesItemExporter',
}
不要帮忙
如何获得utf-8编码的JSON输出
我在重申/扩展一个新的目标
更新:
与刮屑正交,注意无需设置
export PYTHONIOENCODING="utf_8"
运行
> echo { \"name\": \"Düsseldorf\", \"url\": \"Düsseldorf.html\" } > dorf.json
> python -c'import fileinput, json;print json.dumps(json.loads("".join(fileinput.input())),sort_keys=True, indent=4, ensure_ascii=False)' dorf.json > dorf_pp.json
将以失败告终
Traceback (most recent call last):
File "<string>", line 1, in <module>
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 16: ordinal not in range(128)
回溯(最近一次呼叫最后一次):
文件“”,第1行,在
UnicodeEncodeError:“ascii”编解码器无法对位置16中的字符u'\xfc'进行编码:序号不在范围内(128)
更新
我的问题无法回答。UnicodeJsonLinesItemExporter可以工作,但管道的另一部分是罪魁祸首:作为漂亮打印JSON输出的后处理,我使用了
python-mjson.tool in.JSON>out.JSON
这似乎对我来说很有效
>>> a = [{
"name": "D\u00fcsseldorf",
"url": "D\u00fcsseldorf.html"
}]
>>> a
[{'url': 'Düsseldorf.html', 'name': 'Düsseldorf'}]
>>> json.dumps(a, ensure_ascii=False)
'[{"url": "Düsseldorf.html", "name": "Düsseldorf"}]'
# -*- coding: utf-8 -*-
import scrapy
import urllib
class SimpleItem(scrapy.Item):
name = scrapy.Field()
url = scrapy.Field()
class CitiesSpider(scrapy.Spider):
name = "cities"
allowed_domains = ["sitercity.info"]
start_urls = (
'http://en.sistercity.info/countries/de.html',
)
def parse(self, response):
for a in response.css('a'):
item = SimpleItem()
item['name'] = a.css('::text').extract_first()
item['url'] = urllib.unquote(
a.css('::attr(href)').extract_first().encode('ascii')
).decode('utf8')
yield item
使用您问题中引用的提要导出器,它也可以使用另一个存储
# -*- coding: utf-8 -*-
import json
import io
import os
from scrapy.contrib.exporter import BaseItemExporter
from w3lib.url import file_uri_to_path
class CustomFileFeedStorage(object):
def __init__(self, uri):
self.path = file_uri_to_path(uri)
def open(self, spider):
dirname = os.path.dirname(self.path)
if dirname and not os.path.exists(dirname):
os.makedirs(dirname)
return io.open(self.path, mode='ab')
def store(self, file):
file.close()
class UnicodeJsonLinesItemExporter(BaseItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs)
self.file = file
self.encoder = json.JSONEncoder(ensure_ascii=False, **kwargs)
def export_item(self, item):
itemdict = dict(self._get_serialized_fields(item))
self.file.write(self.encoder.encode(itemdict) + '\n')
(必要时删除注释)
这似乎对我有用
# -*- coding: utf-8 -*-
import scrapy
import urllib
class SimpleItem(scrapy.Item):
name = scrapy.Field()
url = scrapy.Field()
class CitiesSpider(scrapy.Spider):
name = "cities"
allowed_domains = ["sitercity.info"]
start_urls = (
'http://en.sistercity.info/countries/de.html',
)
def parse(self, response):
for a in response.css('a'):
item = SimpleItem()
item['name'] = a.css('::text').extract_first()
item['url'] = urllib.unquote(
a.css('::attr(href)').extract_first().encode('ascii')
).decode('utf8')
yield item
使用您问题中引用的提要导出器,它也可以使用另一个存储
# -*- coding: utf-8 -*-
import json
import io
import os
from scrapy.contrib.exporter import BaseItemExporter
from w3lib.url import file_uri_to_path
class CustomFileFeedStorage(object):
def __init__(self, uri):
self.path = file_uri_to_path(uri)
def open(self, spider):
dirname = os.path.dirname(self.path)
if dirname and not os.path.exists(dirname):
os.makedirs(dirname)
return io.open(self.path, mode='ab')
def store(self, file):
file.close()
class UnicodeJsonLinesItemExporter(BaseItemExporter):
def __init__(self, file, **kwargs):
self._configure(kwargs)
self.file = file
self.encoder = json.JSONEncoder(ensure_ascii=False, **kwargs)
def export_item(self, item):
itemdict = dict(self._get_serialized_fields(item))
self.file.write(self.encoder.encode(itemdict) + '\n')
(必要时删除注释)
这似乎确实是一种方式,正如你在问题中看到的那样,它已经被纳入到物品出口商中。为什么输出仍然是U编码和百分比编码字符串的混合?我会考虑包括<代码> URLLIB。PARSE。你能举一个例子,其中既有\u编码的字符串,也有百分比编码的字符串吗?我已经尝试在项目导出器的
export\u item
中使用urlib.parse.unquote
。这个框架的问题是有太多的代码层和钩子,所以不清楚如何获得一些简单的工作。这似乎确实是一种方式,并且它已经包含在项目导出器中,正如您在问题中看到的。为什么输出仍然是U编码和百分比编码字符串的混合?我会考虑包括<代码> URLLIB。PARSE。你能举一个例子,其中既有\u编码的字符串,也有百分比编码的字符串吗?我已经尝试在项目导出器的export\u item
中使用urlib.parse.unquote
。这个框架的问题在于有太多的代码层和钩子,所以不清楚如何获得一些简单的工作方式。Scrapy 1.2(尚未发布)将有一个FEED\u EXPORT\u ENCODING
设置选项:请参阅。同时,您可以使用Scrapy的主分支。还有一个实现:Scrapy 1.2(尚未发布)将有一个FEED\u EXPORT\u ENCODING
设置选项来执行以下操作:请参阅。同时,您可以使用scrapyThere的主分支也有这样的实现:行a.css('::attr(href)).extract_first().encode('ascii')
(第一个解决方案)给出了UnicodeCodeerror:'ascii'编解码器无法对位置1的字符u'\xfc'进行编码:序号不在范围内(128)
。自定义提要CustomFileFeedStorage
不会出现在feed\u STORAGES
挂钩中。你把它挂起来了吗?是的,请删除注释部分,你能添加一个示例url来复制你的错误吗?为了最大程度地再现性,我正在使用一个本地文件(我通过file:///path/to/file.html
)。我就是这样开始提问的。现在,这一切都很好,尽管在使用envvar设置时遇到了困难(PYTHONIOENCODING
,LC\u ALL
,LANG
似乎需要使用默认设置以外的设置)。当我使用http://domain
URL,几乎相同的文件集失败。有些神秘的东西潜伏着。这就好像整个可用的工具链(在最近的OS X/MacPorts安装上)被不支持unicode的部分污染了一样。好笑。。我只是跳过了代码中注释掉的行。现在我明白了为什么要保留CustomFileFeedStorage
的代码了。行a.css('::attr(href)').extract_first().encode('ascii')
(第一种解决方案)给我提供了UnicodeEncodeError:'ascii'编解码器无法在位置1对字符u'\xfc'进行编码:序号不在范围内(128)
。自定义提要CustomFileFeedStorage
不会出现在feed\u STORAGES
挂钩中。你把它挂起来了吗?是的,请删除注释部分,你能添加一个示例url来复制你的错误吗?为了最大程度地再现性,我正在使用一个本地文件(我通过file:///path/to/file.html
)。我就是这样开始提问的。现在,这一切都很好,尽管在使用envvar设置时遇到了困难(PYTHONIOENCODING
,LC\u ALL
,LANG
似乎需要使用默认设置以外的设置)。当我使用http://domain
URL,几乎相同的文件集失败。有些神秘的东西潜伏着。这就好像整个可用的工具链(在最近的OS X/MacPorts安装上)被不支持unicode的部分污染了一样。好笑。。我只是跳过了代码中注释掉的行。现在我明白你为什么保留CustomFileFeedStorage
的代码了。
FEED_EXPORTERS = {
'json': 'myproj.exporter.UnicodeJsonLinesItemExporter'
}
#FEED_STORAGES = {
# '': 'myproj.exporter.CustomFileFeedStorage'
#}
FEED_FORMAT = 'json'
FEED_URI = "out.json"