在 Python 中完成递归异步作业后如何调用函数?

How to call a function after finishing recursive asynchronous jobs in Python?

我用 scrapy 抓取这个 site

我想把所有的子分类保存在一个数组中,然后得到对应的页面(分页)


第一步我有

def start_requests(self):
        yield Request(start_urls[i], callback=self.get_sous_cat)

get_sous_cat 是一个函数,它获取站点的所有子类别,然后异步启动作业以递归地探索子类别。

   def get_sous_cat(self,response):
    #Put all the categgories in a array
    catList = response.css('div.categoryRefinementsSection')
    if (catList):
        for category in catList.css('a::attr(href)').extract():
            category = 'https://www.amazon.fr' + category
            print category
            self.arrayCategories.append(category)
            yield Request(category, callback=self.get_sous_cat)

当所有相应的请求都发送完毕后,我需要调用这个终止函数:

def pagination(self,response):
    for i in range(0, len(self.arrayCategories[i])):
        #DO something with each sub-category

我试过了

def start_requests(self):

    yield Request(start_urls[i], callback=self.get_sous_cat)

    for subCat in range(0,len(self.arrayCategories)):
       yield Request(self.arrayCategories[subCat], callback=self.pagination)

这不是 "recursion",它是异步作业。您需要的是一个全局计数器(受锁保护),如果为 0,请完成:

from threading import Lock

class JobCounter(object):
   def __init__(self, completion_callback, *args, **kwargs):
      self.c = 0
      self.l = Lock()
      self.completion = (completion_callback, args, kwargs)
   def __iadd__(self, n):
      b = false
      with self.l:
         self.c += n
         if self.c <= 0:
            b = true
      if b:
         f, args, kwargs = self.completion
         f(*args, **kwargs)
   def __isub__(self, n):
      self.__iadd__(-n)

每次启动作业时,请执行 counter += 1

每次作业完成时,执行 counter -= 1

注意:这会在最后一个调用作业的线程中完成。如果您想在特定线程中执行此操作,请使用条件而不是锁,并执行 notify() 而不是调用。

干得好,这是个好问题!两件小事:

a) 使用集合而不是数组。这样你就不会重复 b) 站点结构将更改一次month/year。您可能会更频繁地爬行。把蜘蛛一分为二; 1. 创建类别 url 列表并每月运行的那个和 2. 获得 start_urls 第一个

生成的文件的那个

现在,如果您真的想按照现在的方式进行操作,请勾选 spider_idle 信号(参见此处:Scrapy: How to manually insert a request from a spider_idle event callback?)。当没有进一步的 url 可执行并允许您注入更多时,将调用此方法。在那个时候设置一个标志或重置您的列表,以便蜘蛛第二次空闲时(在它抓取所有内容之后),它不会永远重新注入相同的类别 url。

如果在您的情况下,您不想对网址做一些花哨的处理,而只是在其他网址之前抓取类别,这就是请求优先级 属性 的用途(http://doc.scrapy.org/en/latest/topics/request-response.html#topics-request-response-ref-request-subclasses).只需将其设置为例如1 用于您的类别 URL,然后它将在处理任何非类别链接之前跟踪这些链接。这样效率更高,因为它不会像您当前的实现那样加载这些类别页面两次。