耐心听我说。我之所以写下每一个细节,是因为工具链的很多部分都不能很好地处理 Unicode,并且不清楚是什么原因导致的。
PRELUDE
我们首先设置并使用最近的 Scrapy。
source ~/.scrapy_1.1.2/bin/activate
由于终端默认是ascii,而不是unicode,我们设置:
export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8
另外,由于默认情况下 Python 使用 ascii,我们修改编码:
export PYTHONIOENCODING="utf_8"
现在我们准备开始一个 Scrapy 项目。
scrapy startproject myproject
cd myproject
scrapy genspider dorf PLACEHOLDER
我们被告知现在有一只蜘蛛。
Created spider 'dorf' using template 'basic' in module:
myproject.spiders.dorf
我们修改myproject/items.py
to be:
# -*- coding: utf-8 -*-
import scrapy
class MyprojectItem(scrapy.Item):
title = scrapy.Field()
尝试1
现在我们写spider, 依靠urllib.unquote
# -*- coding: utf-8 -*-
import scrapy
import urllib
from myproject.items import MyprojectItem
class DorfSpider(scrapy.Spider):
name = "dorf"
allowed_domains = [u'http://en.sistercity.info/']
start_urls = (
u'http://en.sistercity.info/sister-cities/Düsseldorf.html',
)
def parse(self, response):
item = MyprojectItem()
item['title'] = urllib.unquote(
response.xpath('//title').extract_first().encode('ascii')
).decode('utf8')
return item
最后我们使用一个定制项目出口商(从2011年10月开始)
# -*- coding: utf-8 -*-
import json
from scrapy.exporters import BaseItemExporter
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')
and add
FEED_EXPORTERS = {
'json': 'myproject.exporters.UnicodeJsonLinesItemExporter',
}
to myproject/settings.py
.
现在我们运行
~/myproject> scrapy crawl dorf -o dorf.json -t json
we get
UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 25: ordinal not in range(128)
尝试2
另一种解决方案(Scrapy 1.2的候选解决方案?)是使用spider
# -*- coding: utf-8 -*-
import scrapy
from myproject.items import MyprojectItem
class DorfSpider(scrapy.Spider):
name = "dorf"
allowed_domains = [u'http://en.sistercity.info/']
start_urls = (
u'http://en.sistercity.info/sister-cities/Düsseldorf.html',
)
def parse(self, response):
item = MyprojectItem()
item['title'] = response.xpath('//title')[0].extract()
return item
and the 定制项目出口商
# -*- coding: utf-8 -*-
from scrapy.exporters import JsonItemExporter
class Utf8JsonItemExporter(JsonItemExporter):
def __init__(self, file, **kwargs):
super(Utf8JsonItemExporter, self).__init__(
file, ensure_ascii=False, **kwargs)
with
FEED_EXPORTERS = {
'json': 'myproject.exporters.Utf8JsonItemExporter',
}
in myproject/settings.py
.
我们得到以下 JSON 文件。
[
{"title": "<title>Sister cities of D\u00fcsseldorf \u2014 sistercity.info</title>"}
]
Unicode 不是 UTF-8 编码。虽然这对于几个字符来说是一个微不足道的问题,但如果整个输出都是外语,那么它就会成为一个严重的问题。
如何获得 UTF-8 unicode 格式的输出?