【问题标题】:How to pass a user defined argument in scrapy spider如何在scrapy spider中传递用户定义的参数
【发布时间】:2013-03-14 17:53:13
【问题描述】:

我正在尝试将用户定义的参数传递给 scrapy 的蜘蛛。任何人都可以建议如何做到这一点?

我在某处读到了一个参数-a,但不知道如何使用它。

【问题讨论】:

    标签: python scrapy web-crawler


    【解决方案1】:

    Spider 参数使用-a 选项在crawl 命令中传递。例如:

    scrapy crawl myspider -a category=electronics -a domain=system
    

    蜘蛛可以将参数作为属性访问:

    class MySpider(scrapy.Spider):
        name = 'myspider'
    
        def __init__(self, category='', **kwargs):
            self.start_urls = [f'http://www.example.com/{category}']  # py36
            super().__init__(**kwargs)  # python3
    
        def parse(self, response)
            self.log(self.domain)  # system
    

    取自 Scrapy 文档:http://doc.scrapy.org/en/latest/topics/spiders.html#spider-arguments

    2013 年更新:添加第二个参数

    2015 年更新:调整措辞

    2016 年更新:使用更新的基类并添加 super,感谢 @Birla

    2017 年更新:使用 Python3 super

    # previously
    super(MySpider, self).__init__(**kwargs)  # python2
    

    2018 年更新As @eLRuLL points out,蜘蛛可以访问参数作为属性

    【讨论】:

    • scrapy crawl myspider -a category=electronics -a domain=system
    • 上面的代码对我来说只是部分工作。例如。如果我使用self.domain 定义域,我仍然无法在__init__ 方法之外访问它。 Python 抛出未定义的错误。顺便说一句,你为什么省略了super 电话? PS。我正在使用 CrawlSpider 类
    • @FlyingAtom 如果我误解了请纠正我,但是这些并发调用中的每一个都是蜘蛛的不同实例,不是吗?
    • @Birla,在构造函数中使用 self.domain=domain 来填充类范围变量。
    • @nealmcb __init__ 是蜘蛛类的一个方法。它的实现本身并不会使蜘蛛变得不那么健壮,并且它包含在答案中以表明您可以为关键字参数声明默认值,但正如您所说的那样它是可选的。正如我们去年指出的那样,您不需要使用getattr,您可以将参数作为属性访问,例如self.category 或我们在答案self.domain中看到的@
    【解决方案2】:

    以前的答案是正确的,但是您不必每次要编写scrapy的蜘蛛时都声明构造函数(__init__),您可以像以前一样指定参数:

    scrapy crawl myspider -a parameter1=value1 -a parameter2=value2
    

    在您的蜘蛛代码中,您可以将它们用作蜘蛛参数:

    class MySpider(Spider):
        name = 'myspider'
        ...
        def parse(self, response):
            ...
            if self.parameter1 == value1:
                # this is True
    
            # or also
            if getattr(self, parameter2) == value2:
                # this is also True
    

    而且它确实有效。

    【讨论】:

    • 是的。进入python的黑暗面。
    【解决方案3】:

    使用抓取命令传递参数

    scrapy crawl myspider -a category='mycategory' -a domain='example.com'

    要传递参数以在 scrapyd 上运行,请将 -a 替换为 -d

    卷曲http://your.ip.address.here:port/schedule.json -d spider=myspider -d category='mycategory' -d domain='example.com'

    蜘蛛将在其构造函数中接收参数。

    
    class MySpider(Spider):
        name="myspider"
        def __init__(self,category='',domain='', *args,**kwargs):
            super(MySpider, self).__init__(*args, **kwargs)
            self.category = category
            self.domain = domain

    Scrapy 将所有参数作为蜘蛛属性,您可以完全跳过 init 方法。请注意使用 getattr 方法获取这些属性,以免代码中断。

    
    class MySpider(Spider):
        name="myspider"
        start_urls = ('https://httpbin.org/ip',)
    
        def parse(self,response):
            print getattr(self,'category','')
            print getattr(self,'domain','')
    
    

    【讨论】:

    • 简洁、健壮和灵活!
    【解决方案4】:

    Spider 参数在使用 -a 选项运行 crawl 命令时传递。例如,如果我想将域名作为参数传递给我的蜘蛛,那么我会这样做-

    scrapy crawl myspider -a domain="http://www.example.com"

    并在蜘蛛的构造函数中接收参数:

    class MySpider(BaseSpider):
        name = 'myspider'
        def __init__(self, domain='', *args, **kwargs):
            super(MySpider, self).__init__(*args, **kwargs)
            self.start_urls = [domain]
            #
    

    ...

    它会起作用的:)

    【讨论】:

      【解决方案5】:

      或者,我们可以使用ScrapyD,它公开了一个 API,我们可以在其中传递 start_url 和蜘蛛名称。 ScrapyD 具有停止/启动/状态/列出蜘蛛的 api。

      pip install scrapyd scrapyd-deploy
      scrapyd
      scrapyd-deploy local -p default
      

      scrapyd-deploy 会以 egg 的形式将蜘蛛部署到守护进程中,甚至维护蜘蛛的版本。在启动蜘蛛时,您可以提及要使用的蜘蛛版本。

      class MySpider(CrawlSpider):
      
          def __init__(self, start_urls, *args, **kwargs):
              self.start_urls = start_urls.split('|')
              super().__init__(*args, **kwargs)
          name = testspider
      

      curl http://localhost:6800/schedule.json -d project=default -d spider=testspider -d start_urls="https://www.anyurl...|https://www.anyurl2"

      额外的好处是您可以构建自己的 UI 以接受来自用户的 url 和其他参数,并使用上述 scrapyd schedule API 安排任务

      更多详情请参考scrapyd API documentation

      【讨论】:

        猜你喜欢
        • 2016-11-20
        • 2016-11-17
        • 1970-01-01
        • 2015-04-26
        • 2015-09-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多