scrapy_redis 相关: 多线程更新 score/request.priority
0.背景
使用 scrapy_redis 爬虫, 忘记或错误设置 request.priority(Rule 也可以通过参数 process_request 设置 request.priority),导致提取 item 的 request 排在有序集 xxx:requests 的队尾,持续占用内存。
1.代码实现
遍历 SortedSet 的所有 item 并根据预定义字典对 data 中的 url 进行正则匹配,更新 score 并复制到临时 newkey,最后执行 rename
# -*- coding: UTF-8 -*
import sys
import re
from multiprocessing.dummy import Pool as ThreadPool
from functools import partial try:
input = raw_input #For py2
except NameError:
pass import redis def print_line(string):
print('\n{symbol}{space}{string}'.format(symbol='#'*10, space=' '*5, string=string)) def check_key_scores(key):
try:
total = redis_server.zcard(key)
except redis.exceptions.ResponseError:
print("The value of '{key}' is not a SortedSet".format(key=key))
sys.exit()
except Exception as err:
print(err)
sys.exit() if total == 0:
print("key '{key}' does not exist or has no items".format(key=key))
sys.exit() __, min_score = redis_server.zrange(key, 0, 0, withscores=True)[0]
__, max_score = redis_server.zrange(key, -1, -1, withscores=True)[0] print('score amount')
total_ = 0
# Asuming that score/request.priority is an integer, rather than float number like 1.1
for score in range(int(min_score), int(max_score)+1):
count = redis_server.zcount(key, score, score)
print(score, count)
total_ += count
print("{total_}/{total} items of key '{key}' have an integer priority".format(
total_=total_, total=total_, key=key)) def zadd_with_new_score(startstop, total_items):
data, ori_score = redis_server.zrange(key, startstop, startstop, withscores=True)[0]
for pattern, score in pattern_score:
# data eg: b'\\x80\\x02}q\\x00(X\\x03\\x00\\x00\\x00urlq\\x01X\\x13\\x00\\x00\\x00http://httpbin.org/q\\x02X\\x08\\x00\\x00\\x00callbackq\\x03X\\x
# See /site-packages/scrapy_redis/queue.py
# We don't use zadd method as the order of arguments change depending on
# whether the class is Redis or StrictRedis, and the option of using
# kwargs only accepts strings, not bytes.
m = pattern.search(data.decode('utf-8', 'replace'))
if m:
redis_server.execute_command('ZADD', newkey, score, data)
break
else:
redis_server.execute_command('ZADD', newkey, ori_score, data)
print('{startstop} / {total_items}'.format(
startstop=startstop+1, total_items=total_items)) if __name__ == '__main__': password = 'password'
host = '127.0.0.1'
port = ''
database_num = 0 key = 'test:requests'
newkey = 'temp'
# Request whose url matching any key of keyword_score would be updated with the corresponding value as its score
# Smaller value/score means higher request.priority
keyword_score = {'httpbin': -12, 'apps/details': 1}
pattern_score = [(re.compile(r'url.*?%s.*?callback'%k), v)for (k, v) in keyword_score.items()] threads_amount = 10 redis_server = redis.StrictRedis.from_url('redis://:{password}@{host}:{port}/{database_num}'.format(
password=password, host=host,
port=port, database_num=database_num)) print_line('Step 0: pre check')
check_key_scores(key) print_line('Step 1: copy items and update score')
# total_items = redis_server.zlexcount(key, '-', '+')
total_items = redis_server.zcard(key)
input("Press Enter to copy {total_items} items of '{key}' into '{newkey}' with new score".format(
total_items=total_items, key=key, newkey=newkey))
p = ThreadPool(threads_amount)
p.map(partial(zadd_with_new_score, total_items=total_items), range(total_items))
p.close() #Prevents any more tasks from being submitted to the pool. Once all the tasks have been completed the worker processes will exit.
p.join() #Wait for the worker processes to exit. One must call close() or terminate() before using join(). # For py3
# https://stackoverflow.com/questions/5442910/python-multiprocessing-pool-map-for-multiple-arguments
# with ThreadPool(threads_amount) as pool:
# pool.map(partial(zadd_with_new_score, total_items=total_items), range(total_items))
# print('zadd_with_new_score done') print_line('Step 2: check copy result')
check_key_scores(key)
check_key_scores(newkey) print_line('Step 3: delete, rename and check key')
input("Press Enter to DELETE '{key}' and RENAME '{newkey}' to '{key}'".format(
key=key, newkey=newkey))
print(redis_server.delete(key))
print(redis_server.rename(newkey, key))
check_key_scores(key)
check_key_scores(newkey)
2.运行结果
scrapy_redis 相关: 多线程更新 score/request.priority的更多相关文章
- 拒绝卡顿——在WPF中使用多线程更新UI
原文:拒绝卡顿--在WPF中使用多线程更新UI 有经验的程序员们都知道:不能在UI线程上进行耗时操作,那样会造成界面卡顿,如下就是一个简单的示例: public partial class MainW ...
- Oracle E-Business Suite并发请求的优先级(Concurrent Request Priority)
不少用户抱怨自己的Oracle E-Business Suite并发请求(Concurrent Request)提交了好久,但还是一直在排队,等了好久还没有执行.用户希望对于一些重要性程度高.响应要求 ...
- WPF多线程更新UI的一个解决途径
那么该如何解决这一问题呢?通常的做法是把耗时的函数放在线程池执行,然后切回主线程更新UI显示.前面的updateTime函数改写如下: private async void updateTime() ...
- DataGridView 多线程更新 数据 解决卡顿问题
使用多线程更新DataGridView,防止页面卡顿和卡死的问题 private delegate void UpdateDataGridView(DataTable dt); private voi ...
- 多线程更新已排序的Datagridview数据,造成数据错位
多线程更新已排序的Datagridview数据,触发Datagridview的auto-sort时间,数据重新排序,造成后面更新数据的更新错误. 解决方法: 方法一.设置Datagridview的表头 ...
- Android多线程更新UI的方式
Android下,对于耗时的操作要放到子线程中,要不然会残生ANR,本次我们就来学习一下Android多线程更新UI的方式. 首先我们来认识一下anr: anr:application not rep ...
- C# 通过委托控制进度条以及多线程更新控件
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; usin ...
- scrapy_redis 相关: 将 jobdir 保存的爬虫进度转移到 Redis
0.参考 Scrapy 隐含 bug: 强制关闭爬虫后从 requests.queue 读取的已保存 request 数量可能有误 1.说明 Scrapy 设置 jobdir,停止爬虫后,保存文件目录 ...
- 富客户端 wpf, Winform 多线程更新UI控件
前言 在富客户端的app中,如果在主线程中运行一些长时间的任务,那么应用程序的UI就不能正常相应.因为主线程要负责消息循环,相应鼠标等事件还有展现UI. 因此我们可以开启一个线程来格外处理需要长时间的 ...
随机推荐
- 论decltype和auto的区别
论decltype和auto的区别 decltype和auto的区别 ①对引用变量的不同之处:auto将引用变量赋给变量后,变量的类型为引用变量所对应的变量的类型.而decltype则是为引用类型 ...
- 转载:Linux命令之查看文件占用空间大小-du,df
转载自:<du命令>-linux命令五分钟系列之三 du(disk usage),顾名思义,查看目录/文件占用空间大小 #查看当前目录下的所有目录以及子目录的大小$ du -h $ du ...
- 微信小程序与webview交互实现支付
实现原理:点击h5网页的支付按钮——(跳转)——>嵌套改h5的小程序的支付页面——(处理支付)——>跳转至支付完成后的页面 注意:(1)网页h5中,引入微信的jssdk <scrip ...
- 标签传播算法(Label Propagation Algorithm, LPA)初探
0. 社区划分简介 0x1:非重叠社区划分方法 在一个网络里面,每一个样本只能是属于一个社区的,那么这样的问题就称为非重叠社区划分. 在非重叠社区划分算法里面,有很多的方法: 1. 基于模块度优化的社 ...
- Dell台式机Window10恢复重装window7步骤
1.开机页面出现Dell标识时,连续点击F2 2.进入bois页面,选择boot ,将光标移动到USB启动盘符位置, 3.按 - 号,将 USB Srorage Device 改为第一启动项,F10保 ...
- XGBboost 特征评分的计算原理
xgboost是基于GBDT原理进行改进的算法,效率高,并且可以进行并行化运算,而且可以在训练的过程中给出各个特征的评分,从而表明每个特征对模型训练的重要性, 调用的源码就不准备详述,本文主要侧重的是 ...
- 支付宝沙箱测试-ALI40247
支付宝快速接入文档 测试支付宝APP支付时碰到ALI40247问题 前提:服务端采用沙箱测试. 关于沙箱 如何接入沙箱 沙箱环境是开放平台提供给开发者调试接口的环境,具体操作步骤见沙箱接入指南. Ap ...
- tomcat 8.0安装ssl证书,及centos7.2 的openssl升级到最新版本,及ERR_SSL_OBSOLETE_CIPHER错误解决
openssl官网https://www.openssl.org/source/下载最新的文件 2017-Feb-16 12:03:39 openssl-1.1.0e.tar.gz 安装的时候,可能由 ...
- C# MVC分页简单介绍
ASP.NET MVC中进行分页的方式有多种,这里介绍一种简单实用的方法 一:在实现分页之前,先添加“PagedList”和“PagedList.Mvc”两个组件,具体下载直接在NuGet程序包里收索 ...
- C# 创建Web项目时 可以选择的类型在不同VS版本下的对比
上面这个界面应该是 vs2010的 一. VS2012 .VS2013 其实每个模板的意思,在右边已经显示出来了.Empty,就是一个空的模板,创建后里面除了一个web.config外什么都没有:We ...