最近写了多个scrapy爬虫,想统一管理一下,scrapy爬虫启动需要命令行,最重要的是想实现暂停爬虫的功能,如果在命令行中就很简单,直接ctrl c 那么在程序中对于命令行启动的程序怎么使用ctrl c 呢,直接输入ctrl c 没用。
这个时候看到了有人用signal给相应进程发送信号,这些信号就相当于使用ctrl c 时程序接受到的信号,然后就会停止。
主要使用 os.kill(pid,signal.CTRL_C_EVENT) 这句代码意思是向进程号为pid的进程发送ctrl c信号,使其停止。 对于scrapy的暂停功能就需要ctrl c,如果直接关闭的话scrapy来不及保存状态,导致重启时会非正常重启。
那么,进程id又怎么得到呢,使用os.system运行命令好像没办法得到命令行程序的id(应该没有,有的话指条路),这个时候subprocess就有作用了,subprocess.Popen会开一个进程去运行cmd命令,并且不阻塞当前进程,如果用os.system就会发现只有等运行的程序执行完了才会往下走,而且Poen还提供了运行该命令的进程的id,那么就可以用os.kill(pid,signal.CTRL_C_EVENT)来终结这个进程。
还有一点特别坑的是subprocess的默认工作目录是当前程序所在目录,而我使用scrapy crawl 命令必须在爬虫目录下,这一点可以设置cwd参数来指定工作目录,不能用cd 工作目录的方法来进入工作目录然后使用scrapy crawl,因为即使你cd了,但是执行命令仍然是在程序目录下执行。
针对以上问题最终解决办法是
process = subprocess(“命令”,shell=True,cwd=“工作目录”)
pid = process.pid
time.sleep(60)
os.kill(pid,signal.CTRL_C_EVENT)
这是等程序运行60s后使用ctrl c 终止程序,这个在命令行中启动程序,然后按下ctrl c 会导致一样的结果,对于scrapy爬虫,如果启动时时配置了JOBDIR,使用ctrl c便可以达到暂停爬虫的目的。