Scrapy从unicode转换为utf-8

Gri*_*Mel 4 unicode scrapy python-2.7

我写了一个简单的脚本来从某个站点提取数据.脚本按预期工作,但我不满意输出格式
这是我的代码

class ArticleSpider(Spider):
    name = "article"
    allowed_domains = ["example.com"]
    start_urls = (
        "http://example.com/tag/1/page/1"
    )

    def parse(self, response):
        next_selector = response.xpath('//a[@class="next"]/@href')
        url = next_selector[1].extract()
        # url is like "tag/1/page/2"
        yield Request(urlparse.urljoin("http://example.com", url))

        item_selector = response.xpath('//h3/a/@href')
        for url in item_selector.extract():
            yield Request(urlparse.urljoin("http://example.com", url),
                      callback=self.parse_article)

    def parse_article(self, response):
        item = ItemLoader(item=Article(), response=response)
        # here i extract title of every article
        item.add_xpath('title', '//h1[@class="title"]/text()')
        return item.load_item()
Run Code Online (Sandbox Code Playgroud)

我不满意输出,例如:

[scrapy] DEBUG:从<200 http://example.com/tag/1/article_name > {'title':[u'\ xa0"\ u0412\u041e\u041e\u0411\u0429\u0415-\u0422\u041e\u0421\u0412\u0411\u0411\u0414\u0410\u0411\u0410\u041a\u0410\u041d\u0427\u0418\u0412\u0410\u0415\u0422\u0421\u042f \n''

我想我需要使用自定义ItemLoader类,但我不知道如何.需要你的帮助.

TL; DR我需要转换文本,Scrapy从unicode转换为utf-8

nev*_*stn 7

正如您在下面看到的,这不是Scrapy问题,而是Python本身的问题.它也可能被称为问题:)

$ scrapy shell http://censor.net.ua/resonance/267150/voobscheto_svoboda_zakanchivaetsya

In [7]: print response.xpath('//h1/text()').extract_first()
 "??????-?? ??????? ?????????????"

In [8]: response.xpath('//h1/text()').extract_first()
Out[8]: u'\xa0"\u0412\u041e\u041e\u0411\u0429\u0415-\u0422\u041e \u0421\u0412\u041e\u0411\u041e\u0414\u0410 \u0417\u0410\u041a\u0410\u041d\u0427\u0418\u0412\u0410\u0415\u0422\u0421\u042f"'
Run Code Online (Sandbox Code Playgroud)

你看到的是同一个东西的两个不同的表示 - 一个unicode字符串.

我建议运行爬行-L INFO或添加LOG_LEVEL='INFO'到您的settings.py,以便不在控制台中显示此输出.

一个令人讨厌的事情是,当你保存为JSON时,你会获得转义的unicode JSON,例如

$ scrapy crawl example -L INFO -o a.jl
Run Code Online (Sandbox Code Playgroud)

给你:

$ cat a.jl
{"title": "\u00a0\"\u0412\u041e\u041e\u0411\u0429\u0415-\u0422\u041e \u0421\u0412\u041e\u0411\u041e\u0414\u0410 \u0417\u0410\u041a\u0410\u041d\u0427\u0418\u0412\u0410\u0415\u0422\u0421\u042f\""}
Run Code Online (Sandbox Code Playgroud)

这是正确的,但它需要更多的空间,大多数应用程序同样处理非转义的JSON.

在您的行中添加几行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': 'myproject.settings.MyJsonLinesItemExporter',
    'jl': 'myproject.settings.MyJsonLinesItemExporter',
}
Run Code Online (Sandbox Code Playgroud)

基本上我们所做的只是设置ensure_ascii=False默认的JSON项目导出器.这可以防止逃逸.我希望有一种更简单的方法可以将参数传递给导出器但是我看不到任何东西,因为它们是用这里的默认参数初始化的.无论如何,现在您的JSON文件具有:

$ cat a.jl
{"title": " \"??????-?? ??????? ?????????????\""}
Run Code Online (Sandbox Code Playgroud)

这是更好看,同样有效和更紧凑.