Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/341.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何提供目前正在运行的扭曲反应器?_Python_Scrapy_Twisted - Fatal编程技术网

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

Python 如何提供目前正在运行的扭曲反应器?,python,scrapy,twisted,Python,Scrapy,Twisted,我们正在尝试编程一个机器人,它声称可以从报纸上抓取文章,感谢它的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.

我们正在尝试编程一个机器人,它声称可以从报纸上抓取文章,感谢它的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的新列表后,是否可以暂停反应器并取消其暂停? 我们还有其他解决办法吗

[编辑]对于臭名昭著的。不,多亏了您,这个示例现在运行良好

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的反应堆确实无法重启。如果您想一想,就会发现停止一个事件循环,而让另一个事件启动它,这是违反直觉的。大多数事件驱动的应用程序都是“长时间运行”的,除非出现严重错误,否则不应该停止

不要启动停止重新启动事件循环。启动应用程序,然后再也不要重新启动它(你正在制作一个机器人,所以我假设这个机器人从不睡觉)。使用
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逻辑都应该放在spider本身中,而不是执行脚本中。

AFAIK twister reactor是全局的,所以您可以导入它,并使用它执行任何操作。然而,看看你的代码,我不认为这是你想要做的。通常,人们会用良好的方式处理这个问题。计划
cd项目和刮擦爬行蜘蛛
每8小时运行一次,您就可以开始了!如果您想要更多的原子url分发,我建议您查看redis,或者更具体地说,谢谢您的回答。事实上,我们希望执行一个脚本,执行一次并重复循环(例如,每两小时一次),直到手动停止脚本运行。我们的循环包括执行上面解释的步骤1到步骤4。但有可能提供一个爬行到一个已经打开的扭曲反应堆吗?为什么?让循环长时间运行几乎总是一个坏主意,只是一个cron或systemd作业。我是编程方面的新手,所以我不太了解每件事。请你解释一下什么时候是个坏主意好吗?您使用cron是正确的,但理想情况下,如果有另一个不太复杂的解决方案,它会更好,因为我们希望重新使用该程序,并在以后在其他计算机上升级它。感谢您抽出时间回答我们的问题。不要使用
时间。sleep
这是一个阻塞调用,将阻塞反应器直到睡眠结束。确实,机器人从不休眠,因此如果我理解清楚的话:我们可以在一个循环完成时重复我们的循环,谢谢runner.addCallback(完成爬网时运行)通过将run\u when\u crawl\u down定义为我们的循环?很抱歉造成混淆,这是我的错误
runner.crawl()
返回一个函数,然后可以将回调函数链接到该函数<代码>爬网完成时运行是爬网完成后运行的回调函数的一个示例。我已经更新了答案中的代码示例。对于
反应堆
,它们只有一个,所以你可以简单地从twisted.internet import reactor执行
,并根据需要调用reactor函数。我用你的方法做了一个测试,但问题是它打开了我的第一个爬行器,而不是爬行它的URL集,它打开了我放入回调函数的第二个爬行器,然后爬行同时使用两组URL。这是我们不想要的。我们希望对第一组URL进行爬网,然后查找另一组URL并对其进行爬网。谢谢你的帮助。发生这种情况有几个原因。你需要为我提供你的新代码来有效地帮助你。只需更新您的问题并附加新代码,而不删除原始问题。这是合乎逻辑的,因为回调函数是在deferred之后执行的,而问题是defered是在reactor.run()之前执行的。那么有没有办法在reactor.run()停止之前执行我们的循环呢?