【问题标题】:How to run several versions of one single spider at one time with Scrapy?如何使用 Scrapy 一次运行单个蜘蛛的多个版本?
【发布时间】:2019-03-29 08:27:31
【问题描述】:

我的问题如下:

为了赢得时间,我想运行多个版本的一个蜘蛛。 过程(解析定义)是一样的,项目是一样的,数据库中的集合是一样的。改变的是 start_url 变量。 它看起来像这样:

"https://www.website.com/details/{0}-{1}-{2}/{3}/meeting".format(year,month,day,type_of_meeting)

考虑到日期相同,比如2018-10-24,我想同时推出两个版本:

  • 版本 1 type_of_meeting = pmu
  • 带有type_of_meeting = pmh的版本2

这是我的问题的第一部分。在这里我想知道我是否必须在一个蜘蛛中创建两个不同的类,例如class SpiderPmu(scrapy.Spider):spider.py 中的class SpiderPmh(scrapy.Spider):。但如果这是你认为我必须做的最好的方式,考虑到settings.py,pipelines.py,我不知道如何实现它。我已经从 scrapy.crawler 模块中阅读了有关 CrawlerProcess 的信息,但我不太了解如何在我的项目中实现它。 stack subjectscrapy doc。我不确定那部分 process = CrawlerProcess() process.crawl(MySpider1) process.crawl(MySpider2) process.start() 必须在 spider.py 文件中。最重要的是,我不确定它是否能解决我的问题。

第二部分,是如何考虑不同的日期间隔推出多个版本。

我已经在我的蜘蛛类中创建了一些区间,例如:

  • year = range(2005,2019)
  • month = range(1,13)
  • day = range(1,32)

并把它放在一个循环中。效果很好。

但为了赢得时间,我想推出几只蜘蛛,以不同的年份间隔。

  • 第一个版本year = range(2005,2007)
  • 第二版year = range(2007,2009)
  • 以此类推,直到year = range(2017,2019)

同时使用七个版本意味着快七倍。

我可以为每个年份创建 7 个不同的项目,但我认为这不是最聪明的方法......而且我不确定它是否会在 7 年使用同一个集合数据库时产生冲突不同的项目同时运行。

我希望做一些类似打开 7 个命令的事情:

  1. scrapy crawl spiderpmu 用于版本type_of_race = pmu
  2. "Enter a range of year":raw_input = 2010, 2012 ==> range(2010,2012)
  3. 蜘蛛在爬行

并行,如果这是强制性的,这样做:

  1. scrapy crawl spiderpmh 用于版本 type_of_race = pmh
  2. "Enter a range of year":raw_input = 2010, 2012 ==> range(2010,2012)
  3. 蜘蛛在爬行

如果需要,可能使用一个蜘蛛,或一个项目。

我该怎么办?

PS:我已经安排好了prolipo做代理,Tor网络改IP,USER_AGENT一直在变。所以,我避免被多个蜘蛛同时爬行而被禁止。我的蜘蛛对AUTOTHROTTLE_ENABLED = True 很“礼貌”。我想保持礼貌,但要更快。

Scrapy 版本:1.5.0,Python 版本:2.7.9,Mongodb 版本:3.6.4,Pymongo 版本:3.6.1

【问题讨论】:

    标签: python scrapy


    【解决方案1】:

    所以,我找到了一个受scrapy crawl -a variable=value启发的解决方案

    相关的蜘蛛,在“spiders”文件夹中被转换:

    class MySpider(scrapy.Spider):
    name = "arg"
    allowed_domains = ['www.website.com']
    
        def __init__ (self, lo_lim=None, up_lim=None , type_of_race = None) : #lo_lim = 2017 , up_lim = 2019, type_of_race = pmu
            year  = range(int(lo_lim), int(up_lim)) # lower limit, upper limit, must be convert to integer type, instead this is string type
            month = range(1,13) #12 months
            day   = range(1,32) #31 days
            url   = []
            for y in year:
                for m in month:
                    for d in day:
                        url.append("https://www.website.com/details/{}-{}-{}/{}/meeting".format(y,m,d,type_of_race))
    
            self.start_urls = url #where url = ["https://www.website.com/details/2017-1-1/pmu/meeting",
                                            #"https://www.website.com/details/2017-1-2/pmu/meeting",
                                            #...
                                            #"https://www.website.com/details/2017-12-31/pmu/meeting"
                                            #"https://www.website.com/details/2018-1-1/pmu/meeting",
                                            #"https://www.website.com/details/2018-1-2/pmu/meeting",
                                            #...
                                            #"https://www.website.com/details/2018-12-31/pmu/meeting"]
    
        def parse(self, response):
            ...`
    

    然后,它回答了我的问题:保留一个蜘蛛,并通过多个命令一次运行它的多个版本而不会遇到麻烦。

    没有def __init__,它对我不起作用。我尝试了很多方法,就是这个完美的代码适合我。

    Scrapy 版本:1.5.0,Python 版本:2.7.9,Mongodb 版本:3.6.4,Pymongo 版本:3.6.1

    【讨论】:

      【解决方案2】:

      Scrapy 支持蜘蛛参数。奇怪的是没有简单的文档,但我会尝试填写:

      当您运行crawl 命令时,您可以提供-a NAME=VALUE 参数,这些参数将被设置为您的蜘蛛类实例变量。例如:

      class MySpider(Spider):
          name = 'arg'
          # we will set below when running the crawler
          foo = None 
          bar = None
      
          def start_requests(self):
              url = f'http://example.com/{self.foo}/{self.bar}'
              yield Request(url)
      

      如果我们运行它:

      scrapy crawl arg -a foo=1 -a bar=2
      # will crawl example.com/1/2
      

      【讨论】:

      • 我没有像 f "string" 这样的 f-string。所以我适应了class MySpider(Spider): name = 'arg' global day day = None def start_requests(self): url = "https://www.website.com/details/2018-10-{day}/pmu/meeting".format(**globals()) yield scrapy.Request(url=url, callback=self.parse) 当我运行scrapy crawl arg -a day = 19 甚至day = "19" 时,参数day 保持值None。命令显示:<GET https://www.website.com/details/2018-10-None/pmu/meeting>(failed 1 times): 404 Not Found
      • 我尝试使用self.day,它保留了https://www.website.com/details/2018-10-{self.day}/pmu/meeting,它显示KeyError: 'self' 。这就是为什么我也适应了(**globals())
      • 经过一些研究,您以scrapy crawl arg -a foo=1 -a bar=2 示例启发了我。我找到了一种可行的方法。受此website's example 的启发,我做了class MySpider(scrapy.Spider): name = "arg" allowed_domains = ['www.website.com'] def __init__ (self, day=None, *args, **kwargs) : super(MySpider, self).__init__(*args, **kwargs) self.start_urls = ["https://www.website.com/details/2018-10-{0}/pmu/meeting".format(day)] def parse(self, response): ... 谢谢你的帮助。
      • 你的例子中的构造函数是完全不需要的,除了视觉上的明确性。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-12
      • 1970-01-01
      • 2021-08-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多