Кодирование с использованием 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
Моя проблема в том, что возвращаемые строки являются unicode, и я хочу их кодировать в utf-8. Я не знаю, что это лучший способ сделать это. Я попробовал несколько способов без результата.
Заранее благодарю вас!
Ответы
Ответ 1
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 записывает символы unicode, экранированные (например, \u03a4
) по умолчанию, поскольку не все потоки могут обрабатывать unicode. У него есть возможность записать их как unicode ensure_ascii=False
(см. Docs для json.dumps). Но я не могу найти способ передать этот вариант стандартным экспортерам кормов.
Итак, если вы хотите, чтобы экспортированные элементы записывались в кодировке 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
является просто базовым примером.
Ответ 2
Начиная с Scrapy 1.2.0, вводится новый параметр FEED_EXPORT_ENCODING
. Указав его как utf-8
, вывод JSON не будет экранирован.
То есть добавить в свой settings.py
:
FEED_EXPORT_ENCODING = 'utf-8'
Ответ 3
У меня было много проблем из-за кодирования с помощью python и scrapy.
Чтобы избежать всех проблем декодирования кодирования, лучше всего написать:
unicode(response.body.decode(response.encoding)).encode('utf-8')
Ответ 4
Правильный ответ - ответ Лацка, добавьте в свои настройки:
FEED_EXPORT_ENCODING = 'utf-8'
И попробуйте еще раз, работает для меня.
Ответ 5
Я нахожу простой способ сделать это. Он сохраняет данные 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
Ответ 6
Как упоминалось ранее, экспортер JSON записывает символы unicode, экранированные, и имеет возможность записывать их как unicode ensure_ascii=False
.
Чтобы экспортировать элементы в кодировке utf-8, вы можете добавить это в свой проект 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',
}
Затем запустите:
scrapy crawl spider_name -o output.jl
Ответ 7
Попробуйте добавить следующую строку в конфигурационный файл Scrapy (т.е. settings.py):
FEED_EXPORT_ENCODING = 'utf-8'