如何从Scrapy获得UTF-8编码的unicode输出?

时间:2016-09-19 21:28:00

标签: scrapy

忍受我。我正在编写每个细节,因为工具链的很多部分都不能优雅地处理Unicode,并且不清楚什么是失败的。

PRELUDE

我们首先设置并使用最近的Scrapy。

JObject o = new JObject();

foreach (MotorModel mm in allData) {
    foreach (MotorDataModel mdm : mm.MotorData()) {
        string key = mdm.TimeStamp.ToString(); // Or do your own format
        o[key][mm.MotorName + ":kW"] = mdm.MotorKw;
        o[key][mm.MotorName + ":Speed"] = mdm.MotorSpeed;
        o[key][mm.MotorName + ":TEmp"] = mdm.MotorTemp;
    }
}

由于终端的默认设置是ascii,而不是unicode,我们设置:

source ~/.scrapy_1.1.2/bin/activate

此外,由于默认情况下Python使用ascii,我们修改编码:

export LC_ALL=en_US.UTF-8
export LANG=en_US.UTF-8

现在我们已准备好开始Scrapy项目。

export PYTHONIOENCODING="utf_8"

我们告诉我们现在有一只蜘蛛。

scrapy startproject myproject
cd myproject
scrapy genspider dorf PLACEHOLDER

我们将Created spider 'dorf' using template 'basic' in module: myproject.spiders.dorf 修改为:

myproject/items.py

ATTEMPT 1

现在我们依靠# -*- coding: utf-8 -*- import scrapy class MyprojectItem(scrapy.Item): title = scrapy.Field()

撰写spider
urllib.unquote

最后我们使用custom item exporter(从2011年10月开始)

# -*- 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

并添加

# -*- 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')

FEED_EXPORTERS = { 'json': 'myproject.exporters.UnicodeJsonLinesItemExporter', }

现在我们运行

myproject/settings.py

我们得到了

~/myproject> scrapy crawl dorf -o dorf.json -t json

ATTEMPT 2

另一个解决方案(Scrapy 1.2的候选解决方案?)是使用蜘蛛

UnicodeEncodeError: 'ascii' codec can't encode character u'\xfc' in position 25: ordinal not in range(128)

custom item exporter

# -*- 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

# -*- 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)
FEED_EXPORTERS = { 'json': 'myproject.exporters.Utf8JsonItemExporter', } 中的

我们获得以下JSON文件。

myproject/settings.py

Unicode不是UTF-8编码的。虽然这对于几个字符来说是一个微不足道的问题,但如果整个输出都是外语,则会成为一个严重的问题。

如何以UTF-8 unicode获得输出?

2 个答案:

答案 0 :(得分:12)

在Scrapy 1.2+中有一个FEED_EXPORT_ENCODING选项。当关闭JSON输出中的非{ascii符号的getent passwd时。

答案 1 :(得分:2)

请在尝试1 上试试这个并告诉我它是否有效(我在没有设置所有这些变量的情况下对其进行测试)

def to_write(uni_str):
    return urllib.unquote(uni_str.encode('utf8')).decode('utf8')


class CitiesSpider(scrapy.Spider):
    name = "cities"
    allowed_domains = ["sitercity.info"]
    start_urls = (
        'http://en.sistercity.info/sister-cities/Düsseldorf.html',
    )

    def parse(self, response):
        for i in range(2):
            item = SimpleItem()
            item['title'] = to_write(response.xpath('//title').extract_first())
            item['url'] = to_write(response.url)
            yield item

range(2)用于测试json导出器,以获取可以执行此操作的dicts列表:

# -*- coding: utf-8 -*-
from scrapy.contrib.exporter import JsonItemExporter
from scrapy.utils.serialize import ScrapyJSONEncoder

class UnicodeJsonLinesItemExporter(JsonItemExporter):
    def __init__(self, file, **kwargs):
        self._configure(kwargs, dont_fail=True)
        self.file = file
        self.encoder = ScrapyJSONEncoder(ensure_ascii=False, **kwargs)
        self.first_item = True