免责声明这个问题很难直接回答,需要对scrapy和程序排序有很好的了解才能回答。我很难将问题缩小为更容易直接回答的问题。
AFAIK 无法从项目管道处理程序返回请求。我正在尝试解析论坛中某个类别的所有帖子。我遍历论坛的策略如下:
- 建立一个类别中所有页面的列表,并将它们发送给下载器进行检索。
- 检索每个页面中的所有主题并将它们发送到项目管道。
- 等待所有页面项目被处理(插入到关系数据库中),然后开始遍历每个主题。
我无法弄清楚如何对第 3 步进行排序。我正在使用以下两个对象(最后列出)来协助排序逻辑。category::process_page
是用于遍历主题页面的请求处理程序。
在类别类中:
阶段 1 的结束表示已收到所有主题页面。第 2 阶段的结束意味着项目管道已经处理了所有主题的基础工作。
主题类,代表特定主题列表页面中的所有主题,阶段 1 的结束表示页面中的所有主题已发送到数据库。一旦页面中的每个主题都被添加到数据库中,页面就会从类别中删除 - 一旦所有页面都完成,爬虫应该继续下载所有主题。
那么,如何通过在项目管道中运行的逻辑阻止下载器,以便它可以等待类别阶段 2 结束?是否有一些机器可以解决这个问题?也许我可以从项目管道中重新启动下载器逻辑?
可能有很多方法可以做到这一点,但我是 Python 新手和 C++/C 系统程序员。
注意我最初的设计是在 3-4 种不同的蜘蛛中完成的。第一个检索论坛层次结构,第二个下载所有主题,第三个检索所有帖子,第四个标记需要更新的主题。但是,这个问题肯定有更自然的解决方案,我想将最后 3 只蜘蛛合二为一。
我会接受一个答案,即勺子提供逻辑以启动蜘蛛而不诉诸 bash(能够从 gui 驱动蜘蛛会很好),然后我可以构建一个驱动程序并坚持我的初始设计。
###############################################################################
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
###############################################################################