2012-02-07 13 views
22

Ecco il mio ragnoScrapy testo codifica

from scrapy.contrib.spiders import CrawlSpider,Rule 
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 
from scrapy.selector import HtmlXPathSelector 
from vrisko.items import VriskoItem 

class vriskoSpider(CrawlSpider): 
    name = 'vrisko' 
    allowed_domains = ['vrisko.gr'] 
    start_urls = ['http://www.vrisko.gr/search/%CE%B3%CE%B9%CE%B1%CF%84%CF%81%CE%BF%CF%82/%CE%BA%CE%BF%CF%81%CE%B4%CE%B5%CE%BB%CE%B9%CE%BF'] 
    rules = (Rule(SgmlLinkExtractor(allow=('\?page=\d')),'parse_start_url',follow=True),) 

    def parse_start_url(self, response): 
     hxs = HtmlXPathSelector(response) 
     vriskoit = VriskoItem() 
     vriskoit['eponimia'] = hxs.select("//a[@itemprop='name']/text()").extract() 
     vriskoit['address'] = hxs.select("//div[@class='results_address_class']/text()").extract() 
     return vriskoit 

Il mio problema è che le stringhe restituite sono unicode e voglio loro di codificare in UTF-8. Non so quale sia il modo migliore per farlo. Ho provato diversi modi senza risultato.

Grazie in anticipo!

risposta

32

Scrapy restituisce stringhe in unicode, non ascii. Per codificare tutte le stringhe UTF-8, è possibile scrivere:

vriskoit['eponimia'] = [s.encode('utf-8') for s in hxs.select('//a[@itemprop="name"]/text()').extract()] 

Ma penso che ci si aspetta un altro risultato. Il codice restituisce un articolo con tutti i risultati della ricerca. Per restituire gli articoli per ogni risultato:

hxs = HtmlXPathSelector(response) 
for eponimia, address in zip(hxs.select("//a[@itemprop='name']/text()").extract(), 
          hxs.select("//div[@class='results_address_class']/text()").extract()): 
    vriskoit = VriskoItem() 
    vriskoit['eponimia'] = eponimia.encode('utf-8') 
    vriskoit['address'] = address.encode('utf-8') 
    yield vriskoit 

Aggiornamento

JSON esportatore scrive simboli Unicode escape (ad esempio \u03a4) per impostazione predefinita, perché non tutti i corsi d'acqua in grado di gestire unicode. Ha la possibilità di scriverli come unicode ensure_ascii=False (consultare i documenti per json.dumps). Ma non riesco a trovare il modo di passare questa opzione all'esportatore di feed standard.

Quindi, se si desidera che gli elementi esportati vengano scritti nella codifica utf-8, ad es. per leggerli nell'editor di testo, puoi scrivere pipeline di articoli personalizzati.

pipelines.py:

import json 
import codecs 

class JsonWithEncodingPipeline(object): 

    def __init__(self): 
     self.file = codecs.open('scraped_data_utf8.json', 'w', encoding='utf-8') 

    def process_item(self, item, spider): 
     line = json.dumps(dict(item), ensure_ascii=False) + "\n" 
     self.file.write(line) 
     return item 

    def spider_closed(self, spider): 
     self.file.close() 

Non dimenticate di aggiungere questo pipeline per settings.py:

ITEM_PIPELINES = ['vrisko.pipelines.JsonWithEncodingPipeline'] 

È possibile personalizzare gasdotto per scrivere i dati in formato leggibile più umano, per esempio è possibile generare un report formattato. JsonWithEncodingPipeline è solo un esempio di base.

+0

Ho fatto quello che hai scritto, ma ho ancora ottenere gli stessi risultati: caratteri Unicode. L'unico modo per ottenere utf-8 è usare print vrisko ['eponimia'] invece di yield o return. – mindcast

+0

@mindcast, dove l'hai preso? Cosa fai con gli articoli (salvando in feed JSON, feed CSV o forse pipeline personalizzata)? – reclosedev

+0

crawl raschiato vrisko -o scraped_data.json -t json o anche raschiato strisciare vrisko e vedere i risultati sul mio schermo. So che mi manca qualcosa ma non riesco a capirlo. Grazie per l'impegno. – mindcast

4

Ho avuto un sacco di problemi a causa della codifica con python e scrapy. Per essere sicuri di evitare i problemi di ogni decodifica la codifica, la cosa migliore da fare è scrivere:

unicode(response.body.decode(response.encoding)).encode('utf-8') 
1

trovo un modo semplice per farlo. Si salva i dati JSON per 'SpiderName'.json con 'utf8'

from scrapy.exporters import JsonItemExporter 

class JsonWithEncodingPipeline(object): 

    def __init__(self): 
     self.file = open(spider.name + '.json', 'wb') 
     self.exporter = JsonItemExporter(self.file, encoding='utf-8', ensure_ascii=False) 
     self.exporter.start_exporting() 

    def spider_closed(self, spider): 
     self.exporter.finish_exporting() 
     self.file.close() 

    def process_item(self, item, spider): 
     self.exporter.export_item(item) 
     return item 
0

come è stato detto in precedenza, JSON esportatore scrive simboli Unicode scappato e ha possibilità di scriverli come unicode ensure_ascii=False.

Per esportare gli elementi in UTF-8 codifica è possibile aggiungere questo al file del progetto settings.py:

from scrapy.exporters import JsonLinesItemExporter 
class MyJsonLinesItemExporter(JsonLinesItemExporter): 
    def __init__(self, file, **kwargs): 
     super(MyJsonLinesItemExporter, self).__init__(file, ensure_ascii=False, **kwargs) 

FEED_EXPORTERS = { 
    'jsonlines': 'yourproject.settings.MyJsonLinesItemExporter', 
    'jl': 'yourproject.settings.MyJsonLinesItemExporter', 
} 

Poi gestita:

scrapy crawl spider_name -o output.jl 
3

risposta corretta è Lacek risposta, aggiungere alle impostazioni:

FEED_EXPORT_ENCODING = 'utf-8'

e riprovare, funziona per me.

0

Provate ad aggiungere la seguente riga al file di configurazione per Scrapy (vale a dire settings.py):

FEED_EXPORT_ENCODING = 'utf-8'