当前位置: 首页 > 知识库问答 >
问题:

为scrapy中spider的开始url列表中给出的每个url提供单独的输出文件

许兴文
2023-03-14

我想为我在spider的start_url中设置的每个url创建单独的输出文件,或者以某种方式将输出文件拆分为start url。

以下是我的爬行器的起始URL

start_urls = ['http://www.dmoz.org/Arts/', 'http://www.dmoz.org/Business/', 'http://www.dmoz.org/Computers/']

我想创建单独的输出文件,如

Arts.xml
Business.xml
Computers.xml

我不知道该怎么做。我想通过在item pipeline类的spider_opened方法中实现如下内容来实现这一点,

import re
from scrapy import signals
from scrapy.contrib.exporter import XmlItemExporter

class CleanDataPipeline(object):
    def __init__(self):
        self.cnt = 0
        self.filename = ''

    @classmethod
    def from_crawler(cls, crawler):
        pipeline = cls()
        crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
        crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
        return pipeline

    def spider_opened(self, spider):
        referer_url = response.request.headers.get('referer', None)
        if referer_url in spider.start_urls:
            catname = re.search(r'/(.*)$', referer_url, re.I)
            self.filename = catname.group(1)

        file = open('output/' + str(self.cnt) + '_' + self.filename + '.xml', 'w+b')
        self.exporter = XmlItemExporter(file)
        self.exporter.start_exporting()

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

    def process_item(self, item, spider):
        self.cnt = self.cnt + 1
        self.spider_closed(spider)
        self.spider_opened(spider)
        self.exporter.export_item(item)
        return item

在这里,我试图找到开始url列表中每个已删除项目的引用url。如果在start_url中找到referer url,则将使用该referer url创建文件名。但问题是如何访问spider_opened()方法中的响应对象。如果我可以在那里访问它,我可以基于它创建文件。

找到执行此操作的html" target="_blank">方法有什么帮助吗?提前谢谢!

[编辑]

通过如下更改我的管道代码来解决我的问题。

import re
from scrapy import signals
from scrapy.contrib.exporter import XmlItemExporter

class CleanDataPipeline(object):
    def __init__(self):
        self.filename = ''
        self.exporters = {}

    @classmethod
    def from_crawler(cls, crawler):
        pipeline = cls()
        crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
        crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
        return pipeline

    def spider_opened(self, spider, fileName = 'default.xml'):
        self.filename = fileName
        file = open('output/' + self.filename, 'w+b')
        exporter = XmlItemExporter(file)
        exporter.start_exporting()
        self.exporters[fileName] = exporter

    def spider_closed(self, spider):
        for exporter in self.exporters.itervalues(): 
            exporter.finish_exporting()

    def process_item(self, item, spider):
        fname = 'default'
        catname = re.search(r'http://www.dmoz.org/(.*?)/', str(item['start_url']), re.I)
        if catname:
            fname = catname.group(1)
        self.curFileName = fname + '.xml'

        if self.filename == 'default.xml':
            if os.path.isfile('output/' + self.filename):
                os.rename('output/' + self.filename, 'output/' + self.curFileName)
            exporter = self.exporters['default.xml']
            del self.exporters['default.xml']
            self.exporters[self.curFileName] = exporter
            self.filename = self.curFileName

        if self.filename != self.curFileName and not self.exporters.get(self.curFileName):
            self.spider_opened(spider, self.curFileName)

        self.exporters[self.curFileName].export_item(item)
        return item

还实现了spider中的make\u requests\u from\u url,以设置每个项目的开始\u url。

def make_requests_from_url(self, url):
    request = Request(url, dont_filter=True)
    request.meta['start_url'] = url
    return request

共有3个答案

阎自怡
2023-03-14

以下是我如何在没有设置项目类别的情况下为我的项目做的:

按如下方式从命令行传递参数

scrapy crawl reviews_spider -a brand_name=apple

接收参数并在my_spider.py中设置为spider args

def __init__(self, brand_name, *args, **kwargs):
    self.brand_name = brand_name
    super(ReviewsSpider, self).__init__(*args, **kwargs)

    # i am reading start_urls from an external file depending on the passed argument
    with open('make_urls.json') as f:
        self.start_urls = json.loads(f.read())[self.brand_name]

pipelines.py中

class ReviewSummaryItemPipeline(object):
    @classmethod
    def from_crawler(cls, crawler):
        pipeline = cls()
        crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
        crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
        return pipeline

    def spider_opened(self, spider):
        # change the output file name based on argument
        self.file = open(f'reviews_summary_{spider.brand_name}.csv', 'w+b')
        self.exporter = CsvItemExporter(self.file)
        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
陈增
2023-03-14

只要不将其存储在项目本身中,就无法真正了解起始url。以下解决方案适用于您:

>

一旦您决定将元素传递到管道,请填写response.meta['start\u url']

希望能有帮助。以下链接可能会有所帮助:

http://doc.scrapy.org/en/latest/topics/spiders.html#scrapy.spider.Spider.make_requests_from_url

http://doc.scrapy.org/en/latest/topics/request-response.html?highlight=meta#passing-additional-data-to-callback-functions

戚俊美
2023-03-14

我将实施一种更明确的方法(未经测试):

>

CATEGORIES = ['Arts', 'Business', 'Computers']

根据设置定义您的start_urls

start_urls = ['http://www.dmoz.org/%s' % category for category in settings.CATEGORIES]

添加类别字段项目

在蜘蛛的解析方法中,根据当前的response.url设置类别字段,例如:

def parse(self, response):
     ...
     item['category'] = next(category for category in settings.CATEGORIES if category in response.url)
     ...

在管道中,打开所有类别的导出器,并根据项['category']选择要使用的导出器:

def spider_opened(self, spider):
    ...
    self.exporters = {}
    for category in settings.CATEGORIES:
        file = open('output/%s.xml' % category, 'w+b')
        exporter = XmlItemExporter(file)
        exporter.start_exporting()
        self.exporters[category] = exporter

def spider_closed(self, spider):
    for exporter in self.exporters.itervalues(): 
        exporter.finish_exporting()

def process_item(self, item, spider):
    self.exporters[item['category']].export_item(item)
    return item

您可能需要对其进行一些调整,以使其正常工作,但我希望您已经有了想法-将类别存储在正在处理的项中。根据项目类别值选择要导出到的文件。

希望这有所帮助。

 类似资料:
  • 大家好,来自斯洛文尼亚! 我的问题:我正在使用以下宏在不同的ROI中运行粒子分析: 困扰我的是,我在一个输出文件中得到了所有结果。我需要将每个ROI放在单独的文件中(这样我以后就可以在R中打开它)。所以,如果有任何建议,我将不胜感激,我如何更改宏以便在不同的文件(大纲和结果表)中获得每个ROI粒子分析结果。 谢谢你,杰瑞

  • 我在我的网络应用编程接口项目中使用SwashBuckle Swagger。默认情况下,所有控制器都列在同一个页面上? 有没有办法让每个控制器都有单独的URL,每个URL只显示该控制器的操作?

  • 问题内容: 我正在使用命令来获取目录中的文件名,但输出在一行中。 像这样: 我需要一个内置的替代方法来获取文件名,每个文件名都换行,如下所示: 问题答案: 使用该选项(请注意,这是一个“一个”数字,而不是小写字母“ L”),如下所示: 不过,首先请确保您的支持。GNU coreutils(安装在标准Linux系统上)和Solaris一样;但如果有疑问,请使用或或查看文档。例如:

  • 几天来,我一直在努力修改字符串的每一部分,以包含不同的文件夹。我在PhotoArtist主题中使用超大jQuery滑块。如果您想现场观看,请点击以下链接:http://www.arjanbaagh.com/testsite/sliders-list/bridal-2013-collection/. 我试图实现的是修改字符串,以便在文件名之前包含一个不同的文件夹。我试图使用不同的缩略图的预览。目前,

  • 问题内容: 如何将URL输出的JSON保存到文件中? 例如,来自Twitter搜索API(此http://search.twitter.com/search.json?q=hi) 语言并不重要。 编辑//然后如何将进一步的更新附加到EOF? 编辑2 //确实,答案很好,但是我接受了我认为最优雅的答案。 问题答案: 这在任何语言中都很容易,但是机制各不相同。使用wget和shell: 追加: 使用P

  • 本文向大家介绍给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,找出a,b文件中相同的url?相关面试题,主要包含被问及给定a、b两个文件,各存放50亿个url,每个url各占64字节,内存限制是4G,找出a,b文件中相同的url?时的应答技巧和注意事项,需要的朋友参考一下 这种找相同数据的步骤: 由于单文件总量为5G*64=320G,无法一次读入内存,同样将a文件