2016-09-19 417 views
2

和我在一起。我正在写每一个细节,因为工具链的许多部分不能很好地处理Unicode,并且不清楚失败的原因。如何从Scrapy获得UTF-8编码的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是:

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

最后,我们使用custom item exporter(从早在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') 

,并添加

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

myproject/settings.py

现在我们运行

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

我们得到

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

未遂2

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

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

myproject/settings.pycustom item exporter

# -*- 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文件。

[ 
{"title": "<title>Sister cities of D\u00fcsseldorf \u2014 sistercity.info</title>"} 
] 

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

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

回答

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出口国,要获得一个列表,你可以这样做,而不是:

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

在Scrapy 1.2+有一个FEED_EXPORT_ENCODING选项。当在JSON输出中转义非ASCII字符的FEED_EXPORT_ENCODING = "utf-8"被关闭时。

+1

如何在scrapy spider中添加FEED_EXPORT_ENCODING –

+1

将它放入settings.py文件 –

+0

它工作的很完美! –