2016-09-19 17 views
2

私に同行してください。ツールチェインの多くの部分が正常にUnicodeを処理していないため、細部を書いています。何が失敗しているのかは明らかではありません。ScrapyからUTF-8でエンコードされたユニコードで出力を取得するにはどうすればよいですか?

PRELUDE

私たちは、最初に設定し、最近Scrapyを使用しています。

source ~/.scrapy_1.1.2/bin/activate 

端末のデフォルトはASCIIではなく、ユニコードであるので、我々はセット:

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() 

ATTEMPT 1

は、今、私たちは私たちが使用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 

そして最後に頼る、spiderを書きます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') 

myproject/settings.py

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

を追加します。

今、私たちは

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

ATTEMPT 2

別の解決策(Scrapy 1.2の候補ソリューションは?)クモ

を使用することで取得

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

を実行します

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

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

custom 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) 

次のJSONファイルがあります。

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

ユニコードはUTF-8でエンコードされていません。これは2人のキャラクターにとっては些細な問題ですが、出力全体が外国語であれば深刻な問題になります。

出力をUTF-8ユニコードで取得するにはどうすればよいですか?

答えて

2

あなた試み1でこれを試してみて、それが動作するかどうか私に教えてください(私はこれらすべてのENVを設定せずにテストしてきました。変数)

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 
7

はScrapyで1.2+ FEED_EXPORT_ENCODINGオプションがあります。 FEED_EXPORT_ENCODING = "utf-8" JSON出力の非アスキーシンボルのエスケープがオフになっているとき。

+1

FEED_EXPORT_ENCODINGをスクラピースパイダーに追加するには –

+1

これをsettings.pyファイル –

+0

に入れてください。完璧に動作します! –

関連する問題