itstnd@yandex.ru

Консультации

Разработка и поддержка сайтов

Кодировка результатов парсинга scrapy

 python    

кодировка текста scrapy

Код паука:

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

 


Scrapy возвращает строки в unicode, а не ascii. Чтобы закодировать все строки в UTF-8, вы можете написать:

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

но я думаю, что вы ожидаете другой результат. Код возврата один пункт со всеми результатами поиска. Чтобы вернуть элементы для каждого результата:

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

экспортер JSON пишет символы юникода экранированные (например,\u03a4) по умолчанию, потому что не все потоки могут обрабатывать unicode. Он имеет возможность писать их как Юникод ensure_ascii=False (см. Docs для в формате JSON.свалки) . Но я не могу найти способ передать эту опцию стандартному экспортеру кормов.

поэтому, если вы хотите, чтобы экспортированные элементы были записаны в utf-8 кодирование, например, для чтения их в текстовом редакторе, вы можете написать пользовательский конвейер элементов.

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

Не забудьте добавить этот конвейер в settings.py:

 ITEM_PIPELINES = ['vrisko.pipelines.JsonWithEncodingPipeline']

вы можете настроить конвейер для записи данных в более удобочитаемом виде формат, например, вы можете создать некоторый формированный отчет. JsonWithEncodingPipeline это просто элементарный пример.


Начиная Со Scrapy 1.2.0,новый параметр FEED_EXPORT_ENCODING введена. Указав его как utf-8, вывод JSON не будет экранирован.

это добавить в ваш settings.py:

FEED_EXPORT_ENCODING = 'utf-8'

 Чтобы избежать всех проблем с декодированием кодировки, лучше всего написать:

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


Я нахожу простой способ сделать это. Он сохраняет данные json в «SpiderName».json с ‘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

Как упоминалось ранее, JSON exporter пишет символы unicode, и у него есть возможность записать их как unicode ensure_ascii=False.

для экспорта элементов в кодировке utf-8 вы можете добавить это в:

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',
}

выполнить:

scrapy crawl spider_name -o output.jl