基本上,我有一个名为spiders.py
的文件,在其中我配置了所有蜘蛛,然后使用一个搜寻器对所有蜘蛛进行了射击。这是此文件的源代码:
from scrapy import spiderloader
from scrapy.crawler import CrawlerProcess
from scrapy.utils.project import get_project_settings
from navigator import *
def main():
settings = get_project_settings()
spider_loader = spiderloader.SpiderLoader.from_settings(settings)
process = CrawlerProcess(settings=settings)
for spider_name in spider_loader.list():
process.crawl(spider_name)
process.start()
if __name__ == '__main__':
main()
我要实现的目标是使用subprocess
模块从另一个脚本中启动此蜘蛛,并在执行5分钟后关闭所有蜘蛛(仅使用一个SIGTERM
)。负责此目标的文件为monitor.py
:
from time import sleep
import os
import signal
import subprocess
def main():
spiders_process = subprocess.Popen(["python", "spiders.py"], stdout=subprocess.PIPE,
shell=False, preexec_fn=os.setsid)
sleep(300)
os.killpg(spiders_process.pid, signal.SIGTERM)
if __name__ == '__main__':
main()
当主线程唤醒时,终端显示2018-07-19 21:45:09 [scrapy.crawler] INFO: Received SIGTERM, shutting down gracefully. Send again to force
。但是,即使在收到此消息后,爬虫仍会继续抓取网页。我做错了什么?
OBS :是否可以在spiders.py
内发射所有蜘蛛,而不会阻塞主进程?
答案 0 :(得分:0)
我相信,当scrapy收到SIGTERM时,它会尝试通过首先等待完成所有已发送/预定的请求来正常关闭。最好的选择是限制数量或并发请求,以便更快完成(默认情况下,CONCURRENT_REQUESTS
/ CONCURRENT_REQUESTS_PER_DOMAIN
分别为16和8)或发送两个SIGTERM来指示scrapy做不干净的立即退出。
OBS:是否有可能在spiders.py内部发射所有蜘蛛,而不会阻塞主进程?
process.start()
启动扭曲的反应堆(扭曲的主事件循环),这是一个阻塞调用,要绕开它并在反应堆启动后运行更多代码,可以安排在循环内运行函数。本手册的第一段内容应为您提供一个概念:https://twistedmatrix.com/documents/current/core/howto/time.html。
但是,如果您采用这种方式,则必须确保计划的代码也必须是非阻塞的,否则,如果暂停循环执行的时间过长,可能会开始发生不良情况。因此,time.sleep()
之类的东西必须用等效的方式重写。