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这个库使用起来比较简单,内容不是很多,可以参考官网。