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. 因此我们可以开启一个线程来格外处理需要长时间的 ...
随机推荐
- TensorFlow windows 安装(base anaconda)
Python conda安装之后(19年默认是python3.7) 1.降级到python3.6 2.查看python版本 3.安装tensorflow
- 爬虫框架Scrapy 之(一) --- scrapy初识
Scrapy框架简介 scrapy是基于Twisted的一个第三方爬虫框架,许多功能已经被封装好,方便提取结构性的数据.其可以应用在数据挖掘,信息处理等方面.提供了许多的爬虫的基类,帮我们更简便使用爬 ...
- 【DirectX12】第六章-练习
练习3. (a) //LINELIST std::array<VPosData, > posData = { VPosData({ XMFLOAT3(-2.0f, -1.0f, +1.0f ...
- OOP的魔术方法
1.构造函数:__construct(): 构造函数是类中的一个特殊函数,当我们使用new关键字实例化对象时,相当于调用了类的构造函数. function __construct($name){ $t ...
- 01.QT初学--两个窗口相互切换
//qqwidget.cpp #include "qqwidget.h" #include "ui_qqwidget.h" qqwidget::qqwidget ...
- mysql:The user specified as a definer ('xxx'@'%') does not exist 解决方法
发生这种问题.大概率是用户不存在或者是权限不够 用户不存在.用可视化工具新建一个. 权限不够 ,运行下面命令: 如:我的错误: The user specified as a definer ('mo ...
- PowerPoint 中插入 Latex 公式
做 PPT 用 Latex Beamer 毕竟还是太麻烦,Beamer 毕竟还是更适合学术性的,各种定义各种公式的那种,遇到要画各种图,插入各种图片,进行错综复杂的排版就比较棘手了. 最终还是 Pow ...
- 解锁技能:sass + node-sass多页面应用编译(转载)
传送门:https://blog.csdn.net/wx11408115/article/details/78023466
- LeetCode 解题总结
1. 最长合法括号串 给定只包含'('和')'的字符串,找出最长合法括号串的长度. Example 1: Input: "(()" Output: 2 Explanatio ...
- Object类中方法详解
目录 概述 hashCode方法 getClass方法 toString方法 equals方法 clone方法 finalize方法 概述 Object 是类层次结构的根类.每个类都使用 Object ...