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. Python——设计模式——单例模式

    一个类始终只有一个实例 当你第一次实例化这个类的时候,就创建一个实例化得对象 当你之后再来实例化的时候,就用之前创建的对象 class A: __instance = False def __ini_ ...

  2. cglib 代理实现

    cglib代理的原理是通过继承实现对目标对象的代理 //1.接口 package cn.itcast.service; public interface UserService { void save ...

  3. python学习日记(初识面向对象)

    面向过程 VS 面向对象 面向过程 面向过程的程序设计把计算机程序视为一系列的命令集合,即一组函数的顺序执行.为了简化程序设计,面向过程把函数继续切分为子函数,即把大块函数通过切割成小块函数来降低系统 ...

  4. CF209C Trails and Glades

    题目链接 题意 有一个\(n\)个点\(m\)条边的无向图(可能有重边和自环)(不一定联通).问最少添加多少条边,使得可以从\(1\)号点出发,沿着每条边走一遍之后回到\(1\)号点. 思路 其实就是 ...

  5. Docker:Docker 性质及版本选择 [三]

    一.Docker的性质 Docker的组成其实很简单.你需要搭建registry,专属于你自己的私有仓库,然后就是docker的镜像和docker的容器.Docker的镜像,就类似与windos的系统 ...

  6. matlab中randi代替randint生成随机均匀分布信号的用法

    %%新函数  2*randi([0,1],2,1)-1   等价于老函数     2*randint(2,1)-1 函数形式:randi([imin,imax],m,n) 参数解释: [imin,im ...

  7. MVCC 能解决幻读吗?

    MySQL通过MVCC(解决读写并发问题)和间隙锁(解决写写并发问题)来解决幻读 MySQL InnoDB事务的隔离级别有四级,默认是“可重复读”(REPEATABLE READ). 未提交读(REA ...

  8. LFYZ-OJ ID: 1009 阶乘和

    思路 循环n次,每次计算i的阶乘i!,并加入sum中. n的范围从1~100,这里一定要使用高精度运算,涉及到"高精度乘低精度","高精度加高精度". 避免每次 ...

  9. 如何在IntelliJ IDEA中使用.ignore插件忽略不必要提交的文件

    如何在IntelliJ IDEA中使用.ignore插件忽略不必要提交的文件 最近初学Git,而且在使用的IDE是IntelliJ IDEA,发现IDEA在提交项目到本地仓库的时候,会把.idea文件 ...

  10. 解决 IIS 反向代理ARR URLREWRITE 设置后,不能跨域跳转 return Redirect 问题

    1.选择iis根节点,点击ARR 2.选择代理设置 3.去掉reverse rewrite host in response headers的勾选,点击应用即可