【问题标题】:scrapy text encodingscrapy 文本编码
【发布时间】:2012-02-29 04:09:59
【问题描述】:

这是我的蜘蛛

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。我不知道这是最好的方法。我尝试了几种方法都没有结果。

提前谢谢你!

【问题讨论】:

    标签: scrapy


    【解决方案1】:

    现在我可以将此设置作为命令行参数传递

    >>>scrapy runspider blah.py -o myjayson.json -s FEED_EXPORT_ENCODING=utf-8
    

    【讨论】:

      【解决方案2】:

      您应该将语句FEED_EXPORT_ENCODING = 'utf-8' 添加到您的scrapy 项目的设置文件中。

      【讨论】:

        【解决方案3】:

        尝试将以下行添加到 Scrapy 的配置文件中(即 settings.py):

        FEED_EXPORT_ENCODING = 'utf-8'
        

        【讨论】:

          【解决方案4】:

          由于使用 python 和 scrapy 进行编码,我遇到了很多问题。 为了确保避免每次编码解码问题,最好的办法是写:

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

          【讨论】:

            【解决方案5】:

            从 Scrapy 1.2.0 开始,a new setting FEED_EXPORT_ENCODING is introduced。通过将其指定为utf-8,JSON 输出将不会被转义。

            即添加你的settings.py:

            FEED_EXPORT_ENCODING = 'utf-8'
            

            【讨论】:

            • 谢谢!非常有用且易于更改。
            【解决方案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】:

              我找到了一个简单的方法来做到这一点。它使用 'utf8' 将 json 数据保存到 'SpiderName'.json

              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
              

              【讨论】:

                【解决方案8】:

                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(请参阅json.dumps 的文档)。但我找不到将此选项传递给标准 Feed 导出器的方法。

                因此,如果您希望导出的项目以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 只是基本示例。

                【讨论】:

                • 我做了你写的,但我仍然得到相同的结果:unicode 字符。获取 utf-8 的唯一方法是使用 print vrisko['eponimia'] 而不是 yield 或 return。
                • @mindcast,你从哪里得到的?您如何处理项目(保存到 json 提要、csv 提要或自定义管道)?
                • scrapy crawl vrisko -o scraped_data.json -t json 甚至是 scrapy crawl vrisko 并在我的屏幕上查看结果。我知道我错过了一些东西,但我无法弄清楚。感谢您的努力。
                • 我收到此错误:“line = json.dump(dict(item), ensure_ascii=False) exceptions.TypeError: dump() 至少需要 2 个参数(给定 2 个)”
                • @mindcast,看起来像是由自定义管道和标准 json 导出器写入两次的数据。你在使用scrapy crawl vrisko 命令吗?无需使用-o 选项。
                猜你喜欢
                • 2019-03-06
                • 2018-01-16
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2017-07-15
                • 1970-01-01
                相关资源
                最近更新 更多