python - Scrapy 论坛抓取、项目管道和请求处理器之间的同步策略

标签 python signals scrapy web-crawler sequencing

免责声明 这个问题很难直接回答,你需要对 scrapy 和程序排序有很好的了解才能回答它。对我来说很难将问题压缩成更容易直接回答的问题。

据我所知,无法从项目管道处理程序返回请求。我正在尝试解析论坛中某个类别的所有帖子。我遍历论坛的策略如下:

  1. 构建一个类别中所有页面的列表,并将其发送给下载程序进行检索。
  2. 检索每个页面中的所有主题并将它们发送到项目管道中。
  3. 等待所有页面项目处理完毕(插入关系数据库),然后开始遍历每个主题。

我无法弄清楚如何对步骤 3 进行排序。我正在使用以下两个对象(在末尾列出)来协助排序逻辑。 category::process_page 是用于遍历主题页面的请求处理程序。

在类别类中:

阶段 1 结束表示已收到所有主题页面。 第 2 阶段的结束意味着项目管道已经处理了所有主题的基础工作。

主题类,代表特定主题列表页面中的所有主题,第一阶段结束表示页面中的所有主题都已发送到数据库。一旦页面中的每个主题都被添加到数据库中,该页面就会从类别中删除 - 一旦所有页面完成,爬虫程序应该开始下载所有主题。

那么,如何通过项目管道中运行的逻辑阻止下载程序,以便它可以等待类别第 2 阶段结束? scrapy中有一些机制可以用于此吗?也许我可以从项目管道内重新启动下载器逻辑?

可能有很多方法可以做到这一点,但我是 Python 新手和 C++/C 系统程序员。

注意我最初的设计是在 3-4 个不同的蜘蛛中完成。第一个检索论坛层次结构,第二个下载所有主题,第三个检索所有帖子,第四个标记需要更新的主题。但是,肯定有一个更自然的解决方案来解决这个问题,我想将最后 3 个蜘蛛折叠成一个。

我接受一个答案,即汤匙提供启动蜘蛛的逻辑,而无需诉诸bash(如果能够从图形用户界面驱动蜘蛛就好了),然后我可以构建一个驱动程序并坚持我的初始设计.

###############################################################################
class TopicPageItemBundle:
  def __init__(self,topic_page_url,category_item_bundle):
    self.url = topic_page_url
    self.topics = set()
    self.topics_phase1 = set()
    self.category_item_bundle = category_item_bundle

  def add_topic(self, topic_url):
    self.topics.add(topic_url)
    self.topics_phase1.add(topic_url)

  def topic_phase1_done(self, topic_url):
    self.topics.remove(topic_url)
    if len(self.topics_phase1) == 0:
      return true
    else:
      return false
###############################################################################
class CategoryItemBundle:
  def __init__(self,forum_id):
    self.topic_pages = {}
    self.topic_pages_phase1 = set()
    self.forum_id = forum_id

  def add_topic_page(self,topic_page_url):
    tpib = TopicPageItemBundle(topic_page_url,self)
    self.topic_pages[topic_page_url] = tpib 
    self.topic_pages_phase1.add(topic_page_url)
    self.topic_pages_phase2.add(topic_page_url)

  def process_page(self, response):
    return_items = []
    tp = TopicPage(response,self)
    pagenav = tp.nav()
    log.msg("received " + pagenav.make_nav_info(), log.INFO)

    page_bundle = self.topic_pages[response.url]

    posts = tp.extract_posts(self.forum_id)
    for post in posts:
      if post != None:
        page_bundle.add_topic(post["url"])
        post["page_topic_bundle"] = page_bundle
    return return_items

  # phase 1 represents finishing the retrieval of all topic pages in a forum
  def topic_page_phase1_done(self, topic_page_url):
    self.topic_pages_phase1.remove(topic_page_url)
    if len(self.topic_pages_phase1) == 0:
      return true
    else:
      return false

  def topic_page_phase2_done(self,topic_page_url)
    self.topic_pages_phase2.remove(topic_page_url)
    if len(self.topic_pages_phase2) == 0:
      return true
    else:
      return true
###############################################################################

最佳答案

是否有理由只在获得所有主题的列表并将它们保存到数据库后才开始抓取每个主题?

因为我的 scrapy 流程通常是这样的:获取包含主题列表的页面;查找每个主题的链接,并为每个主题生成一个请求,并带有用于抓取主题的回调;找到列表下一页的链接并为同一回调生成回调;等等。

据我所知,如果您首先从回调中生成一个主题项,然后生成一个请求,则您的管道将立即使用生成的项执行,就像在 scrapy 中一样,一切都是同步的,只有使用twisted 异步下载资源。

关于python - Scrapy 论坛抓取、项目管道和请求处理器之间的同步策略,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11171489/

相关文章:

python - 何时将 http 方法映射到查看方法 django rest framework

python - 如何使其成为列表理解

python - Django 查看返回带有额外信息的查询集

C:通过按 p 而不是 Ctrl + Z 来暂停进程

python - Scrapy - 对项目中的特定蜘蛛(而不是其他蜘蛛)使用 feed 导出器

python - 抓取多个 URL 的 Scrapy 方法

python - 如何缩小 avi 文件的数据集输出

c++ - Sigaction 的替代方案

linux - glibc 和系统调用被信号中断

python - 在 Scrapy 中使用项目