python 中的 OOP(与 scrapy 相关)

OOP in python (related to scrapy)

问题是如何以安全和可维护的方式在对象之间共享数据。

示例: 我已经构建了产生大量蜘蛛的 scrapy 应用程序。虽然每个蜘蛛都连接到单独的管道对象,但我需要比较和排序不同管道之间的数据(例如,我需要按不同项目属性排序的输出:价格、日期等),所以我需要一些共享数据区域。这同样适用于蜘蛛本身(例如,我需要计算最大总请求数)。 第一个实现使用 class 变量在 spiders/pipelines 和每个对象的实例变量之间共享数据。

class MyPipeline(object):
max_price = 0

def process_item(self, item, spider):
if item['price'] > max_price : 
 max_price = item['price']

(实际结构更复杂)然后我想到拥有一堆静态不是 OOP,下一个解决方案是为每个 class 拥有私有 class 数据并使用存储值:

class MyPipelineData:
def __init__(self):
   self.max_price = 0

class SpidersData:
  def __init___(self, total_requests, pipeline_data):
    self.total_requests = total_requests
    self.pipeline_data = pipeline_data #the shared data between pipelines

class MyPipeline(object):
pipeline_data = None

def process_item(self, item, spider):
  if _data is None:  
     _data = spider.data.pipeline_data  #the shared data between pipelines  
  if item['price'] > _data.max_price : 
   _data.max_price = item['price']

 class Spider(scrapy.spider):
 def __init__(self, spider_data):
   self._data = spider_data
  # and the same object of SpiderData is passed to all spiders 

现在我有一个在所有管道之间共享的数据实例(蜘蛛也是如此)。我通常是正确的吗?我应该在 python 中应用与在 C++ 中相同的 OOP 方法吗?

据我了解,您提议的方法是保留每个对象对捕获所有共享数据的共享对象的引用,而且我认为这非常好,特别是如果您适当地命名它所以它的名字表明它是共享的,以提高可读性。

此外,您隐藏了共享对象的内部结构并将它们封装在 process_item() 等方法中,我认为这对于可维护性非常重要(因为共享对象内部结构的变化不必影响任何其他对象)。

但我不确定您引导(即初始化)此共享对象的方式。你有这两行

if _data is None:
  _data = ...

这有点令人惊讶。我不太明白 _data 是什么以及它的定义位置。另外 pipeline_data 被分配给 None 而从未分配给其他任何东西,所以我不确定你在那里的意思。

如果可能的话,我更愿意看到一个名为create_spiders() 的函数创建共享对象,然后一个一个地创建不同的蜘蛛,给它们一个共享对象的引用。这样逻辑就很清晰了。


但是,在您希望共享对象成为单例的特殊情况下,我会考虑在您适当命名的某个模块中将其设为静态对象,也许 Globals.py。然后在您的 Spider 代码中,您会看到类似

的内容
import Globals

class SpiderData:

def update(self):
  self.data.price = 200
  Globals.spiders_data_collector.process(self.data)

在模块 Globals 中,您将初始化对象 spiders_data_collector。我认为这需要更少的代码,这对于可维护性也很重要。