scrapy 多爬虫顺序定时执行

 

scrapy可以在spiders目录下建立多个爬虫文件,常用的启动方式:

 

方法一


 在包含 scrapy.cfg 的目录下, 启动命令为:

scrapy  crawl yourspidername

  

方法二


 调用cmdline模块来启动scrapy

在与settings.py文件同级的目录下新建执行文件, 如 run.py  。 以下有两种写法:

from  scrapy  import cmdline
cmdline.execute('scrapy crawl yourspidername'.split())

 

from scrapy.cmdline import execute 
execute(['scrapy','crawl','yourspidername'])

  

以上只能同时执行一个爬虫,

下面是可以顺序执行多个scrapy爬虫的方法。

 

方法三 


 引入系统os模块,该方法爬虫会顺序执行一遍后结束退出。

import os

os.system("scrapy crawl yourspidername_1") 
os.system("scrapy crawl yourspidername_2")
os.system("scrapy crawl yourspidername_3")

 

启动方式:

python  run.py  直接执行该名为run.py的python文件,下

 ♥ 定时执行

此方法也可以让爬虫不间断的顺序循环执行,设置每个爬虫的执行时间,CLOSESPIDER_TIME=3600 表示3600秒之后强制停止该爬虫。 时间随需要自己定义。

import os

while True:
    os.system("scrapy crawl yourspidername_1 -s CLOSESPIDER_TIMEOUT=3600") 
    os.system("scrapy crawl yourspidername_2 -s CLOSESPIDER_TIMEOUT=7200")  
    os.system("scrapy crawl yourspidername_3 -s CLOSESPIDER_TIMEOUT=3600") 

 

 方法四

 


使用 subprocess模块。subprocess模块的作用是创建一个新的进程让其执行另外的程序,并与它进行通信,获取标准的输入、标准输出、标准错误以及返回码等。

简单的顺序执行爬虫,我们可以这样写:

 

import subprocess

def crawl_work():
    subprocess.Popen('scrapy crawl yourspidername_1').wait()
    subprocess.Popen('scrapy crawl yourspidername_2').wait()


if __name__=='__main__':
    crawl_work()

 

subprocess模块的Popen类来创建进程,它包含很多参数,这里暂不详述。(需要注意的是,这里不需要进程间通信,不需要和PIPE管道相关的参数,默认为None。想要研就一下的朋友可以点这里:参考 )。wait() 等待子进程结束,并返回returncode属性。这里创建了两个子进程,顺序执行后退出。

♥ 定时执行

此方法可以结合schedule模块设置定时任务。

import subprocess
import schedule
import datetime


def crawl_work():
    subprocess.Popen('scrapy crawl yourspidername_1')
    subprocess.Popen('scrapy crawl yourspidername_2')


if __name__ == '__main__':  
    schedule.every(2).hour.do(crawl_work)  
    print('当前时间为{}'.format(datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')))

    while True:
        schedule.run_pending()

  

schedule.run_peding()在死循环里一直监听任务执行状态,这里存在一个问题,spider_1和spider_2是顺序执行,前面的任务执行的时间会影响后面任务的启动时间。如果需要精确的执行每个爬虫任务,那就需要设置多线程,多进程来保持单独定时执行。

schedule.every().minutes.do()可以设置定时任务的时间,官网给出其他的定时方式还有:

schedule.every(10).minutes.do(job)   # 每隔十分钟 执行一次
schedule.every().hour.do(job)    # 每小时 执行一次
schedule.every().day.at("10:30").do(job)   # 每天早上 10:30 执行一次
schedule.every(5).to(10).days.do(job)   # 每隔5--10天 执行一次
schedule.every().monday.do(job)    # 每个周一 执行一次
schedule.every().wednesday.at("13:15").do(job)  # 每个周三的下午13:15 执行一次

 

下面是加了多线程的方式。

 

import datetime
import schedule
import threading
import time
 
def job1():
    print("I'm working for job1")
    subprocess.Popen("scrapy crawl yourspidername_1")

 
def job2():
    print("I'm working for job2")
    subprocess.Popen("scrapy crawl yourspidername_2")
  
 
def job1_task():
    threading.Thread(target=job1).start()
 
def job2_task():
    threading.Thread(target=job2).start()
 
def run():
    schedule.every(3).hour.do(job1_task)
    schedule.every(2).hour.do(job2_task)
 
    while True:
        schedule.run_pending()
        time.sleep(1)

  

 

 

唯一要注意的是,这里面job不应当是死循环类型的,也就是说,这个线程应该有一个执行完毕的出口。一是因为线程万一僵死,会是非常棘手的问题;二是下一次定时任务还会开启一个新的线程,执行次数多了就会演变成灾难。如果schedule的时间间隔设置得比job执行的时间短,一样会线程堆积形成灾难,所以,还是需要注意一下的。 
schedule这个库使用起来比较简单,内容不是很多,可以参考官网。 

 

posted @ 2018-12-15 16:44  椿与湫  阅读(2009)  评论(0编辑  收藏  举报