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中用fork()函数生成的子进程
May 04 Python
Python通过命令开启http.server服务器的方法
Nov 04 Python
python 每天如何定时启动爬虫任务(实现方法分享)
May 21 Python
详解Python中的type和object
Aug 15 Python
Python3 安装PyQt5及exe打包图文教程
Jan 08 Python
简单了解python代码优化小技巧
Jul 08 Python
Python中一个for循环循环多个变量的示例
Jul 16 Python
django Admin文档生成器使用详解
Jul 22 Python
Python爬虫库requests获取响应内容、响应状态码、响应头
Jan 25 Python
Python文本文件的合并操作方法代码实例
Mar 31 Python
python中Pexpect的工作流程实例讲解
Mar 02 Python
从Pytorch模型pth文件中读取参数成numpy矩阵的操作
Mar 04 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入门学习的几个不错的实例代码
2008/07/13 PHP
PHP数组内存耗用太多问题的解决方法
2010/04/05 PHP
php 解压rar文件及zip文件的方法
2014/05/05 PHP
php使用preg_match()函数验证ip地址的方法
2017/01/07 PHP
TP5框架使用QueryList采集框架爬小说操作示例
2020/03/26 PHP
javascript引用对象的方法
2007/01/11 Javascript
EXTJS FORM HIDDEN TEXTFIELD 赋值 使用value不好用的问题
2011/04/16 Javascript
25个好玩的JavaScript小游戏分享
2011/04/22 Javascript
formvalidator验证插件中有关ajax验证问题
2013/01/04 Javascript
jquery实现仿新浪微博评论滚动效果
2015/08/06 Javascript
jQuery实现悬浮在右上角的网页客服效果代码
2015/10/24 Javascript
跟我学习javascript解决异步编程异常方案
2015/11/23 Javascript
进阶之初探nodeJS
2017/01/24 NodeJs
微信小程序 详解页面跳转与返回并回传数据
2017/02/13 Javascript
微信小程序之GET请求的实例详解
2017/09/29 Javascript
vue实现图片滚动的示例代码(类似走马灯效果)
2018/03/03 Javascript
Javascript读取上传文件内容/类型/字节数
2019/04/30 Javascript
Vue页面切换和a链接的本质区别详解
2019/11/12 Javascript
python连接sql server乱码的解决方法
2013/01/28 Python
Python中尝试多线程编程的一个简明例子
2015/04/07 Python
python中尾递归用法实例详解
2015/04/28 Python
使用Python实现企业微信的自动打卡功能
2019/04/30 Python
Python中的支持向量机SVM的使用(附实例代码)
2019/06/26 Python
12个步骤教你理解Python装饰器
2019/07/01 Python
如何通过雪花算法用Python实现一个简单的发号器
2019/07/03 Python
python+selenium 脚本实现每天自动登记的思路详解
2020/03/11 Python
CSS3实现超酷的黑猫警长首页
2016/04/26 HTML / CSS
意大利奢侈品购物网站:Giglio
2018/01/05 全球购物
英国电子产品购物网站:TobyDeals
2018/07/30 全球购物
投标人廉洁自律承诺书
2014/05/26 职场文书
建党伟业的观后感
2015/06/01 职场文书
百年孤独读书笔记
2015/06/29 职场文书
2016党校学习心得体会范文
2016/01/07 职场文书
MySQL 表锁定 LOCK和UNLOCK TABLES的 SQL语法
2022/04/18 MySQL
Mysql 文件配置解析介绍
2022/05/06 MySQL
python绘制云雨图raincloud plot
2022/08/05 Python