如何提供目前运行的扭曲反应器?

How to provide a twisted reactor which is currently running?

我们正在尝试编写一个机器人,它声称可以从报纸上抓取文章,这要归功于它的 RSS 提要。 所以我们希望我们的脚本每天可以多次重复这个步骤:

1) 查看我们列出的 rss 提要

2) 识别我们尚未抓取的文章

3) 将链接添加到要抓取的 url 列表

4) 抓取列出的 url

我们用这段代码实现一次执行这些步骤:

rss_feeds_lemonde = [
'http://www.lemonde.fr/rss/une.xml',
'http://www.lemonde.fr/international/rss_full.xml',
'http://www.lemonde.fr/politique/rss_full.xml',
]

db = sqlite3.connect('newspaper_db')
cursor = db.cursor()
urls = []
already_met = False
site = 'lemonde'

for rss_feed in rss_feeds_lemonde:
    parsed_rss_feed = feedparser.parse(rss_feed)
    for post in parsed_rss_feed.entries:
        url = post.link
        if url.split('.')[1] == site:
            cursor.execute('''SELECT url FROM articles WHERE newspaper = site''')
            rows = cursor.fetchall()
            for row in rows:
                if row[0] == url:
                    already_met = True
            if already_met == False:
                cursor.execute('''INSERT INTO articles(url, newspaper) VALUES(?,?)''', (url, site))
                urls.append(url)
            else:
                already_met = False

cursor.close()
db.commit()
db.close()
if urls != []:
    process = CrawlerProcess()
    process.crawl(LeMondeSpider, start_urls = urls)
    process.start()

问题是扭曲的反应器不可重启,所以它允许我们执行一次我们的步骤。在我们提供新的要抓取的 url 列表后,是否可以暂停 reactor 并取消暂停? 我们还有其他解决方案吗?

[edit] for notorious.no,这个例子现在可以正常工作了,多亏了你!

def run_when_crawl_done(null):
    time.sleep(10)
    urls = [
    'http://www.lefigaro.fr/elections/presidentielles/2017/05/05/35003-20170505ARTFIG00129-comment-ils-veulent-bloquer-le-pen-sans-soutenir-macron-ce-dimanche.php',
    'http://www.lefigaro.fr/elections/presidentielles/2017/05/04/35003-20170504ARTFIG00259-si-marine-le-pen-atteint-40-ca-serait-deja-une-enorme-victoire-dit-sa-niece.php',
    'http://www.lefigaro.fr/elections/presidentielles/2017/05/04/35003-20170504ARTFIG00126-emmanuel-macron-non-je-n-ai-pas-de-compte-aux-bahamas.php',
    ]
    deffered = runner.crawl(LeFigaroSpider, start_urls = urls)
    deffered.addCallback(lambda _: reactor.stop())

urls = [
'http://www.lemonde.fr/les-decodeurs/article/2017/04/26/europe-macron-emploi-la-trumpisation-de-marine-le-pen-sur-tf1_5117479_4355770.html',
'http://www.lemonde.fr/syrie/article/2017/04/26/attaque-chimique-la-france-avance-ses-preuves-contre-damas_5117652_1618247.html',
]

if urls != []:
    configure_logging()
    runner = CrawlerRunner()
    deferred = runner.crawl(LeMondeSpider, start_urls = urls)
    deferred.addCallback(run_when_crawl_done)
    reactor.run()

Twisted的reactor确实无法重启。如果你想一想,你会意识到停止一个事件循环,只是让另一个事件启动它,是违反直觉的。大多数事件驱动的应用程序都是 "long running",除非出现严重错误,否则不应停止。

不要启动-停止-重启事件循环。启动该应用程序,然后永远不要重新启动它(您正在制作一个机器人,所以我假设该机器人从不休眠)。使用 CrawlerRunner 而不是 CrawlerProcess 然后执行 reactor.run()。这允许更多的灵活性,并允许您同时 运行 更多任务。

def run_when_crawl_done(null):
    """
    logic that will be executed after the crawl is done
    """

if urls:
    runner = CrawlerRunner()
    deferred = runner.crawl(LeMondeSpider, start_urls=urls)
    deferred.addCallback(run_when_crawl_done)
    reactor.run()

如果你真的想有一个 python 循环 运行 并充当爬行调度程序(这通常不是一个好主意)你应该使用 subprocess 模块来生成一些抓取过程:

import subprocess
import time

while True:
    subprocess.open('cd project && scrapy crawl spider') 
    time.sleep(60 * 30)

你们所有人 sql 逻辑应该放在蜘蛛本身而不是执行脚本中。