python实现scrapy爬虫每天定时抓取数据的示例代码


Posted in Python onJanuary 27, 2021

1. 前言。

1.1. 需求背景。

  •  每天抓取的是同一份商品的数据,用来做趋势分析。
  • 要求每天都需要抓一份,也仅限抓取一份数据。
  • 但是整个爬取数据的过程在时间上并不确定,受本地网络,代理速度,抓取数据量有关,一般情况下在20小时左右,极少情况下会超过24小时。

1.2. 实现功能。

通过以下三步,保证爬虫能自动隔天抓取数据:
每天凌晨00:01启动监控脚本,监控爬虫的运行状态,一旦爬虫进入空闲状态,启动爬虫。

一旦爬虫执行完毕,自动退出脚本,结束今天的任务。

一旦脚本距离启动时间超过24小时,自动退出脚本,等待第二天的监控脚本启动,重复这三步。

2. 环境。

python 3.6.1

系统:win7

IDE:pycharm

安装过scrapy

3. 设计思路。

3.1. 前提:

目前爬虫是通过scrapy模块自带的cmdline.execute来启动的。

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

3.2. 将自动执行脚本做到scrapy爬虫的外部

(1)每天凌晨00:01启动脚本(控制脚本的存活时间为24小时),监测爬虫的运行状态(需要用一个标记信息来表示爬虫的状态:运行还是停止)。

  • 如果爬虫处于运行状态(前一天爬取数据尚未结束),进入第(2)步;
  • 如果爬虫处于非运行状态(前一天的爬取任务已完成,今天的尚未开始),进入第(3)步;

(2)脚本进入等待阶段,每隔10分钟,检查一下爬虫的运行状态,如(1)。但是一旦发现,脚本的等待时间超过了24小时,则自动退出脚本,因为第二天的监测脚本已经开始运行了,接替了它的任务。

(3)做一些爬虫启动前的准备工作(删除用来续爬的文件,防止爬虫不运行了),启动爬虫爬取数据,待爬虫正常结束后,退出脚本,完成当天的爬取任务。

4. 准备工作。

4.1. 标记爬虫的运行状态。

通过判断文件是否存在的方式来判断爬虫是否处于运行状态:

  • 在爬虫启动时,创建一个isRunning.txt文件。
  • 在爬虫结束时,删除这个isRunning.txt文件。

那么isRunning.txt存在,就说明爬虫正在运行;文件不存在,就说明爬虫不在运行。

# 文件pipelines.py
# 爬虫启动时
checkFile = "isRunning.txt"
class myPipeline:
  def open_spider(self, spider):
    self.client = MongoClient('localhost:27017') # 连接Mongodb
    self.db = self.client['mydata']        # 待存储数据的数据库mydata
    f = open(checkFile, "w")     # 创建一个文件,代表爬虫在运行中
    f.close()
# 文件pipelines.py
# 爬虫正常结束时
checkFile = "isRunning.txt"
class myPipeline:
  def close_spider(self, spider):
    self.client.close()
    isFileExsit = os.path.isfile(checkFile)
    if isFileExsit:
      os.remove(checkFile)

4.2. 爬虫支持续爬,能随时暂停,方便调试。

# 在scrapy项目中添加start.py文件,用于启动爬虫
from scrapy import cmdline
# 在爬虫运行过程中,会自动将状态信息存储在crawls/storeMyRequest目录下,支持续爬
cmdline.execute('scrapy crawl mySpider -s JOBDIR=crawls/storeMyRequest'.split())
# Note:若想支持续爬,在ctrl+c终止爬虫时,只能按一次,爬虫在终止时需要进行善后工作,切勿连续多次按ctrl+c

python实现scrapy爬虫每天定时抓取数据的示例代码

4.3. Log按照每天的日期命名,方便查看和调试

设置Log等级:

# 文件mySpider.py
class mySpider(CrawlSpider):
  name = "mySpider"
  allowed_domains = ['http://photo.poco.cn/']
  custom_settings = {
    'LOG_LEVEL':'INFO', # 减少Log输出量,仅保留必要的信息
    # ...... 在爬虫内部用custom_setting可以让这个配置信息仅对这一个爬虫生效
  }

以日期为Log文件命名

# 文件settings.py
import datetime
BOT_NAME = 'mySpider'
ROBOTSTXT_OBEY = False
startDate = datetime.datetime.now().strftime('%Y%m%d')
LOG_FILE=f"mySpiderlog{startDate}.txt"

4.4. 为数据按日期存储到不同的表(mongodb的集合)中

# 文件pipelines.py
import datetime
GALANCE=f'galance{datetime.datetime.now().strftime("%Y%m%d")}' # 表名
class myPipeline:
  def open_spider(self, spider):
    self.client = MongoClient('localhost:27017') # 连接Mongodb
    self.db = self.client['mydata']        # 待存储数据的数据库mydata
self.db[GALANCE].insert(dict(item))

python实现scrapy爬虫每天定时抓取数据的示例代码

4.5. 编写批处理文件启动爬虫

# 文件run.bat
cd /d F:/newClawer20170831/mySpider
call python main.py
pause

python实现scrapy爬虫每天定时抓取数据的示例代码

5. 实现代码

5.1. 编写python脚本

# 文件timerStartDaily.py
from scrapy import cmdline
import datetime
import time
import shutil
import os

recoderDir = r"crawls"  # 这是为了爬虫能够续爬而创建的目录,存储续爬需要的数据
checkFile = "isRunning.txt" # 爬虫是否在运行的标志

startTime = datetime.datetime.now()
print(f"startTime = {startTime}")

i = 0
miniter = 0
while True:
  isRunning = os.path.isfile(checkFile)
  if not isRunning:            # 爬虫不在执行,开始启动爬虫
    # 在爬虫启动之前处理一些事情,清掉JOBDIR = crawls
    isExsit = os.path.isdir(recoderDir) # 检查JOBDIR目录crawls是否存在
    print(f"mySpider not running, ready to start. isExsit:{isExsit}")
    if isExsit:
      removeRes = shutil.rmtree(recoderDir) # 删除续爬目录crawls及目录下所有文件
      print(f"At time:{datetime.datetime.now()}, delete res:{removeRes}")
    else:
      print(f"At time:{datetime.datetime.now()}, Dir:{recoderDir} is not exsit.")
    time.sleep(20)
    clawerTime = datetime.datetime.now()
    waitTime = clawerTime - startTime
    print(f"At time:{clawerTime}, start clawer: mySpider !!!, waitTime:{waitTime}")
    cmdline.execute('scrapy crawl mySpider -s JOBDIR=crawls/storeMyRequest'.split())
    break #爬虫结束之后,退出脚本
  else:
    print(f"At time:{datetime.datetime.now()}, mySpider is running, sleep to wait.")
  i += 1
  time.sleep(600)    # 每10分钟检查一次
  miniter += 10
  if miniter >= 1440:  # 等待满24小时,自动退出监控脚本
    break

5.2. 编写bat批处理文件

# 文件runTimerRunDaily.bat
cd /d F:/newClawer20170831/mySpider
call python timerStartDaily.py
pause

6. 部署。

6.1. 添加计划任务。

参考以下这篇博客部署windows计划任务:

有关windows计划任务相关设置的详细说明如下:

https://technet.microsoft.com/zh-cn/library/cc722178.aspx

6.2. 注意事项。

(1)在添加计划任务时,要按照如下图进行勾选(只在用户登录时运行),才能弹出下面的cmd任务界面,方便观察和调试。

python实现scrapy爬虫每天定时抓取数据的示例代码 

python实现scrapy爬虫每天定时抓取数据的示例代码

(2)由于爬虫运行时间很长,如果按照默认设置,在凌晨运行实例时,上一次启动尚未结束,会导致这次启动失败,所以要更改默认设置为(如果此任务已经运行:并行运行新实例。保护机制在于每个启动脚本在等待24小时候会自动退出,来保证不会重复启动)。

python实现scrapy爬虫每天定时抓取数据的示例代码

(3)如果想支持续传,只能按一次 ctrl + c 来停止爬虫运行。因为终止爬虫时,爬虫需要做一些善后工作,如果连续按多次ctrl + c来停止爬虫,爬虫将来不及善后,会导致无法续爬。 6.3. 效果展示。

正常执行完成:

python实现scrapy爬虫每天定时抓取数据的示例代码

正在执行中:

python实现scrapy爬虫每天定时抓取数据的示例代码

到此这篇关于python实现scrapy爬虫每天定时抓取数据的示例代码的文章就介绍到这了,更多相关python scrapy定时抓取内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!

Python 相关文章推荐
python使用cPickle模块序列化实例
Sep 25 Python
Python PyQt5标准对话框用法示例
Aug 23 Python
python实现分页效果
Oct 25 Python
Python批量更改文件名的实现方法
Oct 29 Python
Python最火、R极具潜力 2017机器学习调查报告
Dec 11 Python
selenium python 实现基本自动化测试的示例代码
Feb 25 Python
python实现猜拳小游戏
Apr 05 Python
Python tkinter常用操作代码实例
Jan 03 Python
Python 绘制可视化折线图
Jul 22 Python
Python操作word文档插入图片和表格的实例演示
Oct 25 Python
Python基于Socket实现简易多人聊天室的示例代码
Nov 29 Python
python编程的核心知识点总结
Feb 08 Python
使用bandit对目标python代码进行安全函数扫描的案例分析
Jan 27 #Python
用Python实现定时备份Mongodb数据并上传到FTP服务器
Jan 27 #Python
python re.match()用法相关示例
Jan 27 #Python
selenium+python实现基本自动化测试的示例代码
Jan 27 #Python
Python开发.exe小工具的详细步骤
Jan 27 #Python
Python中正则表达式对单个字符,多个字符和匹配边界等使用
Jan 27 #Python
python正则表达式re.match()匹配多个字符方法的实现
Jan 27 #Python
You might like
php读取html并截取字符串的简单代码
2009/11/30 PHP
求PHP数组最大值,最小值的代码
2011/10/31 PHP
解析如何修改phpmyadmin中的默认登陆超时时间
2013/06/25 PHP
jquery1.4.2 for Visual studio 2010 模板文件
2010/07/14 Javascript
某页码显示的helper 少量调整,另附js版
2010/09/12 Javascript
js检查页面上有无重复id的实现代码
2013/07/17 Javascript
js动态删除div元素基本思路及实现代码
2014/05/08 Javascript
jQuery实现鼠标悬停显示提示信息窗口的方法
2015/04/30 Javascript
javascript冒泡排序小结
2016/04/10 Javascript
JS上传图片预览插件制作(兼容到IE6)
2016/08/07 Javascript
微信小程序  Mustache语法详细介绍
2016/10/27 Javascript
jQuery 遍历map()方法详解
2016/11/04 Javascript
Javascript之深入浅出prototype
2017/02/06 Javascript
详解vue-cli 脚手架项目-package.json
2017/07/04 Javascript
原生JS实现小小的音乐播放器
2017/10/16 Javascript
详解React-Native全球化多语言切换工具库react-native-i18n
2017/11/03 Javascript
浅谈vue引用静态资源需要注意的事项
2018/09/28 Javascript
vue远程加载sfc组件思路详解
2019/12/25 Javascript
JS的时间格式化和时间戳转换函数示例详解
2020/07/27 Javascript
element-ui封装一个Table模板组件的示例
2021/01/04 Javascript
python实现的希尔排序算法实例
2015/07/01 Python
Python的Django框架中的数据库配置指南
2015/07/17 Python
使用EduBlock轻松学习Python编程
2018/10/08 Python
利用python提取wav文件的mfcc方法
2019/01/09 Python
利用SVG和CSS3来实现一个炫酷的边框动画
2015/07/22 HTML / CSS
印度最大的时尚购物网站:Myntra
2018/09/13 全球购物
英国卫浴商店:Ergonomic Design
2019/09/22 全球购物
加拿大领先的时尚和体育零售商:Sporting Life
2019/12/15 全球购物
个人求职简历的自我评价
2013/10/19 职场文书
护理专业的自荐信
2013/10/22 职场文书
挑战杯创业计划书的写作指南
2014/01/07 职场文书
孝敬父母的活动方案
2014/08/28 职场文书
2014年师德师风工作总结
2014/11/25 职场文书
教师工作决心书
2015/02/04 职场文书
2015年公务员个人工作总结
2015/04/24 职场文书
小学生节水倡议书
2015/04/29 职场文书