如何在继承的crawspider中重用基于scrapy的spider的解析方法?

2024-05-19 18:42:06 发布

您现在位置:Python中文网/ 问答频道 /正文

我目前有一个基于Spider的Spider,它是我为抓取start_urls的输入JSON数组而编写的:

from scrapy.spider import Spider
from scrapy.contrib.spiders import CrawlSpider, Rule
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor

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

import json
import datetime
import re

class AtlanticFirearmsSpider(Spider):
    name = "atlantic_firearms"
    allowed_domains = ["atlanticfirearms.com"]

    def __init__(self, start_urls='[]', *args, **kwargs):
      super(AtlanticFirearmsSpider, self).__init__(*args, **kwargs)
      self.start_urls = json.loads(start_urls)

    def parse(self, response):
      l = ItemLoader(item=AtlanticFirearmsItem(), response=response)
      product = l.load_item()
      return product

我可以像这样从命令行调用它,它的工作非常出色:

^{pr2}$

不过,我正在尝试添加一个基于crawspider的spider,用于对继承自它的整个站点进行爬网,并重用parse方法逻辑。我的第一次尝试是这样的:

class AtlanticFirearmsCrawlSpider(CrawlSpider, AtlanticFirearmsSpider):
    name = "atlantic_firearms_crawler"
    start_urls = [
        "http://www.atlanticfirearms.com"
    ]
    rules = (
        # I know, I need to update these to LxmlLinkExtractor
        Rule(SgmlLinkExtractor(allow=['detail.html']), callback='parse'),
        Rule(SgmlLinkExtractor(allow=[], deny=['/bro', '/news', '/howtobuy', '/component/search', 'askquestion'])),
    )

用这个蜘蛛

scrapy crawl atlantic_firearms_crawler

爬网网站,但从不分析任何项目。我想是因为CrawlSpider apparently has its own definition of ^{},所以我把事情搞砸了。在

当我将callback='parse'改为callback='parse_item',并将AtlanticFirearmsSpider中的parse方法重命名为parse_item时,它工作得非常好,爬网了整个站点并成功地解析了项目。但是如果我再次尝试调用我原来的atlantic_firearms蜘蛛,它会以NotImplementedError错误,显然是因为基于蜘蛛的蜘蛛确实希望人们将解析方法定义为parse。在

对于我来说,在这些spider之间重用我的逻辑的最佳方法是什么,这样既可以提供start_urls的JSON数组,又可以进行完整的站点爬网?在


Tags: 方法fromimportselfparseitemurlsstart
1条回答
网友
1楼 · 发布于 2024-05-19 18:42:06

你可以在这里避免多重继承。在

把两个蜘蛛合在一起。如果start_urls将从命令行传递-它的行为将类似于CrawlSpider,否则类似于常规蜘蛛:

from scrapy import Item
from scrapy.contrib.spiders import CrawlSpider, Rule

from foo.items import AtlanticFirearmsItem
from scrapy.contrib.loader import ItemLoader
from scrapy.contrib.linkextractors import LinkExtractor

import json


class AtlanticFirearmsSpider(CrawlSpider):
    name = "atlantic_firearms"
    allowed_domains = ["atlanticfirearms.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://www.atlanticfirearms.com/"]
            self.rules = [
                Rule(LinkExtractor(allow=['detail.html']), callback='parse_response'),
                Rule(LinkExtractor(allow=[], deny=['/bro', '/news', '/howtobuy', '/component/search', 'askquestion']))
            ]

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

    def parse_response(self, response):
        l = ItemLoader(item=AtlanticFirearmsItem(), response=response)
        product = l.load_item()
        return product

或者,只需将parse()方法中的逻辑提取到一个库函数中,并从两个不相关的、独立的spider调用。在

相关问题 更多 >