0.参考

Scrapy 隐含 bug: 强制关闭爬虫后从 requests.queue 读取的已保存 request 数量可能有误

1.说明

Scrapy 设置 jobdir,停止爬虫后,保存文件目录结构:

crawl/apps/
├── requests.queue
│   ├── active.json
│   ├── p0
│   └── p1
├── requests.seen
└── spider.state

requests.queue/p0 文件保存 priority=0 的未调度 request, p-1 对应实际 priority=1 的高优先级 request,转移到 redis 有序集合时,score 值越小排序越靠前,因此取 score 为 -1。以此类推,p1 对应 priority=-1 的低优先级 request。

requests.seen 保存请求指纹过滤器对已入队 request 的 hash 值,每行一个值。

spider.state 涉及自定义属性的持久化存储,不在本文处理范围以内。

2.实现代码

import os
from os.path import join
import re
import struct import redis def sadd_dupefilter(jobdir, redis_server, name):
"""See python/lib/site-packages/scrapy/dupefilters.py""" file = join(jobdir, 'requests.seen')
with open(file) as f:
print('Processing %s, it may take minutes...'%file)
key = '%s:dupefilter'%name
for x in f:
redis_server.sadd(key, x.rstrip())
print('Result: {} {}'.format(key, redis_server.scard(key))) def zadd_requests(jobdir, redis_server, name):
"""See python/lib/site-packages/queuelib/queue.py""" SIZE_FORMAT = ">L"
SIZE_SIZE = struct.calcsize(SIZE_FORMAT) key = '%s:requests'%name
queue_dir = join(jobdir, 'requests.queue')
file_list = os.listdir(queue_dir)
file_score_dict = dict([(f, int(f[1:])) for f in file_list
if re.match(r'^p-?\d+$', f)])
for (file, score) in file_score_dict.items():
print('Processing %s, it may take minutes...'%file)
f = open(join(queue_dir, file), 'rb+')
qsize = f.read(SIZE_SIZE)
total_size, = struct.unpack(SIZE_FORMAT, qsize)
f.seek(0, os.SEEK_END) actual_size = 0
while True:
if f.tell() == SIZE_SIZE:
break
f.seek(-SIZE_SIZE, os.SEEK_CUR)
size, = struct.unpack(SIZE_FORMAT, f.read(SIZE_SIZE))
f.seek(-size-SIZE_SIZE, os.SEEK_CUR)
data = f.read(size)
redis_server.execute_command('ZADD', key, score, data)
f.seek(-size, os.SEEK_CUR)
actual_size += 1
print('total_size {}, actual_size {}, score {}'.format(
total_size, actual_size, score))
print('Result: {} {}'.format(key, redis_server.zlexcount(key, '-', '+'))) if __name__ == '__main__':
name = 'test'
jobdir = '/home/yourproject/crawl/apps'
database_num = 0
# apps/
# ├── requests.queue
# │   ├── active.json
# │   ├── p0
# │   └── p1
# ├── requests.seen
# └── spider.state password = 'password'
host = '127.0.0.1'
port = ''
redis_server = redis.StrictRedis.from_url('redis://:{password}@{host}:{port}/{database_num}'.format(
password=password, host=host,
port=port, database_num=database_num)) sadd_dupefilter(jobdir, redis_server, name)
zadd_requests(jobdir, redis_server, name)

3.运行结果

scrapy_redis 相关: 将 jobdir 保存的爬虫进度转移到 Redis的更多相关文章

  1. 使用git stash命令保存和恢复进度

    使用git stash命令保存和恢复进度 git stash 保存当前工作进度,会把暂存区和工作区的改动保存起来.执行完这个命令后,在运行git status命令,就会发现当前是一个干净的工作区,没有 ...

  2. git stash 保存和恢复进度

    1. stash当前修改 git stash会把所有未提交的修改(包括暂存的和非暂存的)都保存起来,用于后续恢复当前工作目录. 比如下面的中间状态,通过git stash命令推送一个新的储藏,当前的工 ...

  3. scrapy_redis 相关: 查看保存的数据

    0.参考资料 https://redis.io/topics/data-types-intro An introduction to Redis data types and abstractions ...

  4. scrapy_redis 相关: 多线程更新 score/request.priority

    0.背景 使用 scrapy_redis 爬虫, 忘记或错误设置 request.priority(Rule 也可以通过参数 process_request 设置 request.priority), ...

  5. Post请求data参数构造及巧用js脚本显示爬虫进度

    小爬最近随着对python中字符串.json等理解进一步加深,发现先前我随笔中提到的data构造和传参方法略复杂,原本有更简单的方法,Mark如下. 先前小爬我使用的requests.post请求中d ...

  6. iPhone/iOS图片相关(读取、保存、绘制、其它相关)

    http://blog.csdn.net/jerryvon/article/details/7526147 20:50:42 一.读取图片 1.从资源(resource)读取 UIImage* ima ...

  7. Agumater 爬虫进度带上了百分比,消除了.0

  8. scrapy分布式爬虫scrapy_redis一篇

    分布式爬虫原理 首先我们来看一下scrapy的单机架构:     可以看到,scrapy单机模式,通过一个scrapy引擎通过一个调度器,将Requests队列中的request请求发给下载器,进行页 ...

  9. Scrapy 框架,爬虫文件相关

    Spiders 介绍 由一系列定义了一个网址或一组网址类如何被爬取的类组成 具体包括如何执行爬取任务并且如何从页面中提取结构化的数据. 简单来说就是帮助你爬取数据的地方 内部行为 #1.生成初始的Re ...

随机推荐

  1. Linux 版本svn安装

    CentOS6.5离线安装subversion 下载 linux rpm安装包 (我只下载了subversion-1.6.12-1.rhel5.x86_64.rpm),直接安装时会提示缺少依赖,在 r ...

  2. luogu P2071 座位安排

    这个题可以被分为两部分 1.匈牙利算法(板子) 2.邻接表存图(好像这不能称为第二部分) 每一排能坐两个人,那就把一排拆成两个点, 用匈牙利算法求最大匹配 每个人都只想坐两排,说明每个人只会连四条边 ...

  3. GateOne Web SSH 环境搭建

    环境配置安装python及tornadoyum -y install python-pippip install tornado GateOne安装下载源码:git clone https://git ...

  4. ETL过程跑完后,使用python发送邮件

    目标库中,如果有行数为0的表,使用python发送邮件 # -*- coding:utf-8 -*- # Author: zjc # Description:send monitor info to ...

  5. 第一节: 结合EF的本地缓存属性来介绍【EF增删改操作】的几种形式

    一. 背景 说起EF的增删改操作,相信很多人都会说,有两种方式:① 通过方法操作  和  ② 通过状态控制. 相信你在使用EF进行删除或修改操作的时候,可能会遇到以下错误:“ The object c ...

  6. JavaScript null和undefined的区别

    前言 1995年javascript诞生时,最初像Java一样,只设置了null作为表示"无"的值.根据C语言的传统,null被设计成可以自动转为0 但是,javascript的设 ...

  7. css长度单位学习(em,rem,px,vw,vh)

    绝对长度单位 绝对长度单位代表一个物理测量 [像素px(pixels)] 像素,为影像显示的基本单位,译自英文"pixel",pix是英语单词picture的常用简写,加上英语单词 ...

  8. JavaScript的数据类型和变量

    1.  数据类型:JS使用弱类型,共4种基本类型,其数据可以是变量,也可以是常量. a)         数值(整数和实数) b)         字符串型(用“”号或‘’括起来的字符或数值) c)  ...

  9. ajax向Django前后端提交请求和CSRF跨站请求伪造

    1.ajax登录示例 urls.py from django.conf.urls import url from django.contrib import admin from app01 impo ...

  10. I. Max answer(RMQ预处理前缀和)

    题目链接: https://nanti.jisuanke.com/t/38228 题目大意:给你n个数,让你找出一个区间中f的最大值,具体的f计算方法,这段区间的和乘以这段区间的最小值. 具体思路:我 ...