在电商数据采集场景中,爬虫常因网络波动、服务器重启、IP 封禁等问题中断。若缺乏断点续爬机制,重启后需从头开始,不仅浪费带宽与时间,还可能因重复采集导致数据冗余。Redis 凭借其高性能、原子操作、多样数据结构的特性,成为实现断点续爬的理想工具。本文将从核心原理到实战代码,完整讲解实现方案。

一、为什么选择 Redis 实现断点续爬?

断点续爬的核心需求是记录 “已爬状态” 和 “待爬任务”,确保中断后能从上次进度继续。Redis 的优势恰好匹配这些需求:

  1. 高性能读写:电商爬虫 URL 队列常达百万级,Redis 每秒 10 万 + 的读写速度可支撑高并发任务调度;
  2. 原子操作保障:分布式爬虫多实例抢任务时,Redis 的LPOP/SPOP等原子命令可避免重复取 URL;
  3. 多样数据结构
    • 待爬 URL 队列:用List(FIFO)或Sorted Set(按优先级排序);
    • 已爬 URL 记录:用Set(O (1) 判断是否重复,自动去重);
    • 临时数据缓存:用Hash存储已采集但未入库的数据,防止爬后丢数据;

      4.持久化机制:支持 RDB/AOF 持久化,即使 Redis 重启,断点数据也不会丢失。

二、核心实现逻辑:三大核心模块

断点续爬的本质是 “状态记录” 与 “进度恢复”,需围绕以下三个模块设计 Redis 存储方案:

1. 待爬 URL 队列(任务池)

作用:存储尚未采集的电商 URL(如商品列表页、详情页),确保爬虫能持续获取任务。

数据结构选择

  • 简单场景(无优先级):用List,通过LPUSH(添加任务)和RPOP(获取任务)实现 FIFO 队列;
  • 复杂场景(有优先级):用Sorted Set,为不同 URL 设置分数(如 “商品详情页 = 10,分类列表页 = 5”),通过ZADD添加任务,ZRANGEBYSCORE按优先级取任务。

示例命令(List 实现):

# 添加待爬URL(如电商商品详情页)
LPUSH e_commerce:wait_urls "https://xxx.com/item/123"
LPUSH e_commerce:wait_urls "https://xxx.com/item/456"# 取出待爬URL(爬虫消费任务)
RPOP e_commerce:wait_urls  # 返回"https://xxx.com/item/123"

2. 已爬 URL 记录(去重池)

作用:记录已采集完成的 URL,避免重复爬取(电商 URL 重复爬会导致数据冗余,还可能触发反爬)。

数据结构选择:Set(天然去重,判断 URL 是否已爬的时间复杂度为 O (1))。

核心逻辑

  1. 爬虫获取待爬 URL 后,先通过SISMEMBER判断是否在已爬集合中;
  2. 若已存在,直接跳过;若不存在,执行采集逻辑;
  3. 采集成功后,用SADD将 URL 加入已爬集合。

示例命令

# 判断URL是否已爬
SISMEMBER e_commerce:done_urls "https://xxx.com/item/123"  # 返回0(未爬)# 采集成功后,加入已爬集合
SADD e_commerce:done_urls "https://xxx.com/item/123"

3. 临时数据缓存(防丢失)

作用:电商数据采集后,若直接写入数据库时中断(如数据库宕机),会导致数据丢失。用 Redis 临时缓存已采集数据,待数据库恢复后批量入库。

数据结构选择:Hash,key 为 “任务 ID / 商品 ID”,value 为 JSON 格式的采集数据(便于后续解析)。

示例命令

# 缓存已采集的商品数据(key=商品ID,value=JSON)
HSET e_commerce:temp_data "123" '{"title":"iPhone 15","price":5999,"stock":100}'
HSET e_commerce:temp_data "456" '{"title":"华为Mate 60","price":4999,"stock":50}'# 数据库恢复后,批量获取数据入库
HGETALL e_commerce:temp_data  # 返回所有临时数据
# 入库成功后删除临时数据
DEL e_commerce:temp_data

三、实战代码:Python + Redis 实现电商断点续爬

以 “采集某电商商品详情页” 为例,结合redis-py库实现完整断点续爬逻辑,框架采用通用爬虫结构(可适配 Scrapy、Requests 等)。

1. 环境准备

# 安装依赖
pip install redis requests beautifulsoup4

2. 完整代码实现

import redis
import requests
from bs4 import BeautifulSoup
import json# 1. 初始化Redis连接(开启持久化,避免断点数据丢失)
redis_client = redis.Redis(host="localhost",port=6379,db=0,decode_responses=True  # 自动解码为字符串,避免b''格式
)# 2. 配置Key前缀(避免与其他项目冲突)
WAIT_URLS_KEY = "e_commerce:wait_urls"  # 待爬URL队列
DONE_URLS_KEY = "e_commerce:done_urls"  # 已爬URL集合
TEMP_DATA_KEY = "e_commerce:temp_data"  # 临时数据缓存# 3. 初始化待爬队列(首次运行时添加初始URL,后续从Redis恢复)
def init_wait_urls(initial_urls):for url in initial_urls:# 先判断是否已在待爬/已爬队列,避免重复添加if not (redis_client.sismember(DONE_URLS_KEY, url) or url in redis_client.lrange(WAIT_URLS_KEY, 0, -1)):redis_client.lpush(WAIT_URLS_KEY, url)print(f"初始化完成,待爬URL数量:{redis_client.llen(WAIT_URLS_KEY)}")# 4. 采集函数(解析商品数据)
def crawl_item(url):try:response = requests.get(url, headers={"User-Agent": "Mozilla/5.0"})response.raise_for_status()  # 抛出HTTP错误soup = BeautifulSoup(response.text, "html.parser")# 解析商品数据(示例:标题、价格、商品ID)item_id = url.split("/")[-1]  # 从URL提取商品IDtitle = soup.find("h1", class_="product-title").get_text(strip=True)price = soup.find("span", class_="price").get_text(strip=True)return {"item_id": item_id,"title": title,"price": price,"url": url}except Exception as e:print(f"采集失败({url}):{str(e)}")# 采集失败的URL重新加入待爬队列(避免永久丢失)redis_client.lpush(WAIT_URLS_KEY, url)return None# 5. 主爬虫逻辑(断点续爬核心)
def run_crawler(initial_urls=None):# 首次运行初始化待爬队列,后续从Redis恢复if initial_urls and redis_client.llen(WAIT_URLS_KEY) == 0:init_wait_urls(initial_urls)print(f"开始爬虫,当前待爬URL数量:{redis_client.llen(WAIT_URLS_KEY)}")while True:# 1. 从Redis获取待爬URL(原子操作,避免多实例重复取)url = redis_client.rpop(WAIT_URLS_KEY)if not url:print("所有任务完成!")break# 2. 判断URL是否已爬(防止重复采集)if redis_client.sismember(DONE_URLS_KEY, url):print(f"URL已爬,跳过:{url}")continue# 3. 执行采集item_data = crawl_item(url)if not item_data:continue# 4. 缓存采集数据(待入库)redis_client.hset(TEMP_DATA_KEY, item_data["item_id"], json.dumps(item_data))print(f"采集成功,缓存数据:{item_data['title']}")# 5. 将URL加入已爬集合(标记完成)redis_client.sadd(DONE_URLS_KEY, url)# 6. (可选)批量入库:当临时数据达到100条时,写入数据库if redis_client.hlen(TEMP_DATA_KEY) >= 100:batch_insert_db()# 6. 批量入库函数(示例,需根据实际数据库适配)
def batch_insert_db():print("开始批量入库...")# 从Redis获取所有临时数据temp_data = redis_client.hgetall(TEMP_DATA_KEY)if not temp_data:return# 模拟数据库写入(实际项目替换为MySQL/MongoDB等)for item_id, data_json in temp_data.items():item = json.loads(data_json)# 执行入库SQL/API:如 insert into products (item_id, title, price) values (...)print(f"入库成功:{item['title']}")# 入库成功后,清空临时数据redis_client.delete(TEMP_DATA_KEY)print("批量入库完成!")# 7. 启动爬虫(首次运行需传入初始URL,后续无需)
if __name__ == "__main__":# 初始URL(如电商分类页下的商品列表URL)initial_urls = ["https://xxx.com/item/123","https://xxx.com/item/456","https://xxx.com/item/789"]# 启动爬虫(中断后重启,会自动从Redis恢复进度)run_crawler(initial_urls)

四、关键优化:适配电商场景的特殊需求

1. 分布式爬虫的任务分配

若需多台机器同时爬取(如采集百万级商品),可通过 Redis 实现分布式任务调度:

  • 所有实例共享同一 Redis 的wait_urls队列;
  • 利用 Redis 的原子命令RPOP(或SPOP),确保每个 URL 仅被一个实例获取;
  • 已爬集合done_urls全局共享,避免多实例重复爬取。

2. 电商数据更新的处理

电商商品价格、库存会实时变化,仅靠 “已爬集合” 会导致旧数据无法更新。解决方案:

  • 用Sorted Set存储已爬 URL,分数设为 “最后爬取时间戳”;
  • 爬虫每次取 URL 前,先清理 “过期” 任务(如 7 天前爬过的 URL 重新加入待爬队列):
import time
current_time = time.time()
# 找出7天前(604800秒)爬过的URL,重新加入待爬队列
expired_urls = redis_client.zrangebyscore(DONE_URLS_KEY, 0, current_time - 604800)
for url in expired_urls:redis_client.lpush(WAIT_URLS_KEY, url)redis_client.zrem(DONE_URLS_KEY, url)  # 从已爬集合删除

3. Redis 持久化配置(防数据丢失)

默认 Redis 数据存于内存,若 Redis 宕机,断点数据会丢失。需开启持久化:

  1. AOF 持久化(推荐):记录所有写命令,重启时重新执行命令恢复数据;
    • 配置文件redis.conf:appendonly yes,appendfsync everysec(每秒同步一次);

      2.RDB 持久化:定时生成数据快照,适合备份;
    • 配置文件:save 3600 1(1 小时内至少 1 次写操作则生成快照)。

五、总结

利用 Redis 实现电商爬虫断点续爬,核心是通过 “待爬队列(List/Sorted Set)+ 已爬集合(Set)+ 临时缓存(Hash)” 三大模块,记录爬虫状态。相比传统文件存储(如 JSON/CSV),Redis 的高性能、原子操作、分布式支持,能更好应对电商场景的高并发、大数据量需求。

实际项目中,还需结合反爬策略(如 IP 池、UA 轮换)、数据库批量入库优化,进一步提升爬虫稳定性与效率。若需适配 Scrapy 框架,可直接使用scrapy-redis库(底层原理与本文一致,无需重复造轮子)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/bicheng/96202.shtml
繁体地址,请注明出处:http://hk.pswp.cn/bicheng/96202.shtml
英文地址,请注明出处:http://en.pswp.cn/bicheng/96202.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

决策树概念与原理

决策树简介决策树是一种树形结构树中每个内部节点表示一个特征上的判断,每个分支代表一个判断结果的输出,每个叶子节点代表一种分类结果(仅举例无其他意义或隐喻)就像一个女孩去相亲,那么首先询问是否大于30,大于则不见&#xff0…

SQL面试题及详细答案150道(116-135) --- 高级查询与函数篇

《前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux… 。 前后端面试题-专栏总目录 文章目录 一、本文面试题目录 116. 如何使用CASE语句实…

VeRL:强化学习与大模型训练的高效融合框架

本文由「大千AI助手」原创发布,专注用真话讲AI,回归技术本质。拒绝神话或妖魔化。搜索「大千AI助手」关注我,一起撕掉过度包装,学习真实的AI技术! 1 概述:VeRL的起源与核心价值 VeRL(Versatile…

2. 计算机系统基础知识

1 计算机系统概述 计算机系统 (Computer System) 是指用于数据管理的计算机硬件、软件及网络组成的系统。 计算机系统可划分为硬件(子系统)和软件(子系统)两部分。硬件由机械、电子元器件、磁介质和光介质等物理实体构成,例如处理器(含运算单元和控制单元)、存储器、…

国产EtherCAT从站芯片FCE1353与N32G435 MCU功能板测试流程

上期推荐,我们在前期介绍了FCE1353与国民N32G435 MCU开发板的基本情况,本期主要介绍此开发板的测试流程,以便用户拿到此板做功能验证、兼容性测试、可靠性测试时更加便捷地提高开发验证效率。01概述FCE1353_N32G435RBL7_GPIO_V1 开发板主要通…

向日葵亮点16功能解析:被控端“快速解锁”

向日葵16重磅上线,本次更新新增了诸多实用功能,提升远控效率,实现应用融合突破设备边界,同时全面提升远控性能,操作更顺滑、画质更清晰!无论远程办公、设计、IT运维、开发还是游戏娱乐,向日葵16…

深度解析:IService 与 ServiceImpl 的区别

在使用 MyBatis-Plus 开发业务逻辑时,IService 和 ServiceImpl 是经常遇到的两个核心类。很多初学者会疑惑: 为什么要定义 IService?ServiceImpl 又解决了什么问题?它们之间到底有什么区别与联系? 本文将结合源码与应用…

YOLO12 改进、魔改|通道自注意力卷积块CSA-ConvBlock,通过动态建模特征图通道间的依赖关系,优化通道权重分配,在强化有效特征、抑制冗余信息

在分割的研究中,传统卷积神经网络(CNN)存在两大关键问题:一是池化操作虽能降低计算复杂度,却会导致特征图中有效空间信息丢失,尤其太阳暗条这类不规则、精细结构的特征易被削弱;二是传统 CNN 对…

JuiceFS分布式文件系统

对象存储虽然具备极高的扩展性和成本优势,却缺乏对POSIX语义的支持,导致许多应用无法直接使用。正是在这样的背景下,JuiceFS 应运而生——它巧妙地融合了对象存储的弹性与传统文件系统的易用性,为现代应用提供了一种全新的存储解决…

nginx配置前端请求转发到指定的后端ip

nginx conf配置 配置把“前端静态文件”和“后端接口”统一收在 同一个 server{} 块 里,通过 两条 location 做分流,其中 /api 这条 location 用到了一点“小技巧”把路径裁掉后再转发。下面按执行顺序逐句拆解,告诉你“请求是怎么被转发到 1…

HTML 各种标签的使用说明书

HTML 各种标签的使用说明书 1. HTML 简介 HTML(HyperText Markup Language,超文本标记语言)是用于创建网页的标准标记语言。它使用一系列标签来描述网页的结构和内容,这些标签被浏览器解释并渲染成用户看到的网页。HTML是构建We…

从关键词到语义理解:小陌引擎如何重构AI搜索优化逻辑?

引言:AI搜索时代的范式转变在传统互联网时代,SEO(搜索引擎优化)是企业数字营销的核心策略,通过关键词密度、外链建设等技术手段提升网页在搜索引擎结果页(SERP)中的排名。然而,随着生…

ADE explorer遇到XVFB服务器的问题

遇到这个报错,是因为服务器没有安装xvfb的原因。yum install Xvfb即可解决问题。

期权的套利怎么理解?

期权套利是利用期权价格之间的不合理偏差,通过构建对冲组合获取无风险利润的策略。其核心逻辑基于“无套利定价原则”——若存在价格偏差,市场力量会迅速修正,套利者通过反向操作锁定利润。期权的套利怎么理解?一、主要套利类型与…

RabbitMQ 重试机制 和 TTL

目录 1. 重试机制 1.1 简介 1.2 配置文件 1.3 消费者确认机制为 auto 时 1.4 消费者确认机制为 manual 时 2. TTL 2.1 设置消息的过期时间 2.2 设置队列的过期时间 2.3 给过期队列中消息设置过期时间 1. 重试机制 1.1 简介 在消息传递过程中, 可能会遇到各种问题, …

四、FVP启动linux

目录 1 实验目的及环境 1.1 实验目的 1.2 实验环境 1.2.1 拉取代码 1.2.2搭建交叉编译环境 2 相关镜像编译 2.1 TF-A镜像编译 2.2 U-Boot镜像编译 2.3 Linux Kernel镜像编译 2.4 构建跟文件系统 3 启动linux内核 3.1 启动脚本构建 3.2 启动Linux内核 1 实验目的及环境 1.1 实验…

浅聊一下微服务的服务保护

在微服务架构里,服务间调用关系错综复杂,一个服务出问题很可能引发连锁反应,也就是 “雪崩”。今天就带大家从零开始学习 Sentinel,这款阿里开源的微服务保护工具,帮你解决雪崩难题,做好流量控制、隔离降级…

ECharts Gallery:Apache官方数据可视化模板库,助你快速制作交互图表并实现深度定制

你有没有过这种时候?手里攥着一堆 Excel 数据,想做个直观的图表给同事看,用 Excel 自带的图表吧,样式丑不说,稍微复杂点的交互(比如点击柱子显示详情)根本做不了;想自己用代码写吧&a…

[数据结构——lesson3.单链表]

目录 引言 学习目标: 1.什么是链表 2.链表的分类 2.1 单向链表和双向链表 (1)单向链表 (2)双向链表 2.2 带头结点链表和不带头结点链表 (1)带头结点链表 (2)不带头结点链表 2.3 循环链表和不循环链表 (1)循环链表 (2)非循环链表 3.链表的实…

从零深入理解嵌入式OTA升级:Bootloader、IAP与升级流程全解析

引言(Opening)想象一下,你开发的一款智能水杯、一个环境监测设备或者一台共享充电宝,已经部署到了成千上万的用户手中。突然,你发现了一个软件bug,或者需要增加一个酷炫的新功能。你不可能派人跑到每个设备…