基于`Spider`类,根据传入的参数委托给`SitemapSpider`或`CrawlSpider`?

时间:2015-02-17 03:53:17

标签: scrapy

我之前asked a question关于重复使用我编写的parse方法,以便我的蜘蛛表现不同,具体取决于它是否在start_urls参数中传递。如果是,它应抓取这些给定的URL(不要关注),但如果不抓取,则应抓取整个站点(按照链接)。

我得到的答案非常有用且运作良好,并产生了CrawlSpider这样的定义:

from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors import LinkExtractor
from scrapy.selector import Selector

from foo.items import FooItem
from scrapy.contrib.loader import ItemLoader

import json
import datetime
import re

class FooSpider(CrawlSpider):
    name = "foo"
    allowed_domains = ["example.com"]

    def __init__(self, start_urls=None, *args, **kwargs):
        if start_urls:
            self.start_urls = json.loads(start_urls)
            self.rules = []
            self.parse = self.parse_response
        else:
            self.start_urls = ["http://example.com/"]
            self.rules = [
                Rule(LinkExtractor(allow=[], deny=['/blog']), follow=True, callback='parse_response'),
            ]

        super(FooSpider, self).__init__(*args, **kwargs)

    def parse_response(self, response):
      sel = Selector(response)
      if not(sel.css('div.product-view')):
          return None
      l = ItemLoader(item=FooItem(), response=response)
      product = l.load_item()
      return product

但是,我现在刚刚发现example.com有一个我可以使用的站点地图,而不是必须抓取整个站点。所以我像这样更新我的蜘蛛:

class FooSpider(SitemapSpider):
    name = "foo"
    sitemap_urls = ['http://example.com/sitemap.xml']
    sitemap_rules = [('/', 'parse_response')]

但此时我发现SitemapSpider的行为与CrawlSpider不同,并且不会以与我之前定义相同的方式接受start_urls。那么有没有办法保留名为"foo"的单个蜘蛛的先前行为,该蜘蛛根据start_urls参数委托行为?

我不太了解Python,并且开始认为我可以有一个FooSpider基类,它根据参数动态返回一个子类,但现在我认为它可能无效。我开始思考的草图代码(不工作):

class FooSpider(Spider):
    name = "foo"

    def __init__(self, start_urls=None, *args, **kwargs):
        if start_urls:
            self.start_urls = json.loads(start_urls)
            FooCrawlSpider.__init__(self, *args, **kwargs)
        else:
            FooSitemapSpider.__init__(self, *args, **kwargs)

    def parse_response(self, response):
      sel = Selector(response)
      if not(sel.css('div.product-view')):
          return None
      l = ItemLoader(item=FooItem(), response=response)
      product = l.load_item()
      return product

class FooCrawlSpider(CrawlSpider, FooSpider):
    allowed_domains = ["example.com"]
    rules = []
    parse = self.parse_response

class FooSitemapSpider(SitemapSpider, FooSpider):
    sitemap_urls = ['http://example.com/sitemap.xml']
    sitemap_rules = [('/', 'parse_response')]

我缺乏Python知识在这里引起了我的注意。任何想法,将不胜感激!最糟糕的情况我总是可以创建具有不同name s的单独蜘蛛。

0 个答案:

没有答案