分布式爬虫去重:Python + Redis实现高效URL去重

本文涉及的产品
实时数仓Hologres,5000CU*H 100GB 3个月
实时计算 Flink 版,5000CU*H 3个月
Elasticsearch Serverless检索通用型,资源抵扣包 100CU*H
简介: 分布式爬虫去重:Python + Redis实现高效URL去重
  1. 引言
    在互联网数据采集(爬虫)过程中,URL去重是一个关键问题。如果不对URL进行去重,爬虫可能会重复抓取相同页面,导致资源浪费、数据冗余,甚至触发目标网站的反爬机制。
    对于单机爬虫,可以使用Python内置的set()或dict进行去重,但在分布式爬虫环境下,多个爬虫节点同时工作时,内存级的去重方式不再适用。此时,需要一个共享存储来管理已爬取的URL,而Redis凭借其高性能、低延迟和分布式支持,成为理想选择。
  2. URL去重的常见方法
    2.1 基于内存的去重(单机适用)
    Python set()
    最简单的去重方式,适用于小规模数据,但无法持久化,重启后数据丢失。
    visited_urls = set()
    if url not in visited_urls:
    visited_urls.add(url)

    抓取逻辑

    ● Bloom Filter(布隆过滤器)
    节省内存,但有一定误判率(可能误判未访问的URL为已访问),适用于海量URL去重。
    2.2 基于数据库的去重(分布式适用)
    ● Redis Set / Redis HyperLogLog
    ○ SET 结构存储URL,精确去重(100%准确)。
    ○ HyperLogLog 适用于统计不重复元素数量(有一定误差,但占用内存极小)。
    ● 关系型数据库(MySQL, PostgreSQL)
    通过UNIQUE约束去重,但性能较低,不适合高并发爬虫。
    ● 分布式键值存储(如Memcached)
    类似Redis,但功能较少,通常仅用于缓存。
  3. Redis 在分布式爬虫去重中的优势
    Redis 是一个高性能的内存数据库,支持多种数据结构,适用于分布式爬虫去重,主要优势包括:
  4. 高性能:数据存储在内存中,读写速度极快(10万+ QPS)。
  5. 持久化:支持RDB/AOF持久化,避免数据丢失。
  6. 分布式支持:可通过集群模式扩展,支持多爬虫节点共享数据。
  7. 丰富的数据结构:SET(精确去重)、HyperLogLog(近似去重)、Bitmap(位图去重)等。
  8. Python + Redis 实现分布式URL去重
    4.1 方案1:使用 Redis Set 精确去重
    import redis

class RedisUrlDedupe:
def init(self, redis_host='localhost', redis_port=6379, redis_db=0):
self.redis = redis.StrictRedis(
host=redis_host, port=redis_port, db=redis_db
)
self.key = "visited_urls"

def is_visited(self, url):
    """检查URL是否已访问"""
    return self.redis.sismember(self.key, url)

def mark_visited(self, url):
    """标记URL为已访问"""
    self.redis.sadd(self.key, url)

示例用法

deduper = RedisUrlDedupe()
url = "https://example.com/page1"

if not deduper.is_visited(url):
deduper.mark_visited(url)
print(f"抓取: {url}")
else:
print(f"已访问: {url}")
优点:
● 100% 准确,无误差。
● 适用于中小规模爬虫(百万级URL)。
缺点:
● 存储所有URL,内存占用较高。
4.2 方案2:使用 Redis HyperLogLog 近似去重
如果允许少量误差(~0.8%),可使用HyperLogLog节省内存:
class RedisHyperLogLogDedupe:
def init(self, redis_host='localhost', redis_port=6379, redis_db=0):
self.redis = redis.StrictRedis(
host=redis_host, port=redis_port, db=redis_db
)
self.key = "hll_visited_urls"

def is_visited(self, url):
    """检查URL是否可能已访问(可能有误判)"""
    before = self.redis.pfcount(self.key)
    after = self.redis.pfadd(self.key, url)
    return after == 0  # 如果添加后计数未变,说明可能已存在

示例用法

hll_deduper = RedisHyperLogLogDedupe()
url = "https://example.com/page1"

if not hll_deduper.is_visited(url):
print(f"抓取: {url}")
else:
print(f"可能已访问: {url}")
优点:
● 内存占用极低(12KB可存储数亿URL)。
● 适用于超大规模爬虫(如全网爬取)。
缺点:
● 有少量误判(可能将未访问的URL误判为已访问)。
4.3 方案3:使用 Redis Bloom Filter(需安装RedisBloom模块)
Redis 官方提供 RedisBloom 模块,支持布隆过滤器(需额外安装):

需确保Redis服务器加载了RedisBloom模块

class RedisBloomFilterDedupe:
def init(self, redis_host='localhost', redis_port=6379, redis_db=0):
self.redis = redis.StrictRedis(
host=redis_host, port=redis_port, db=redis_db
)
self.key = "bloom_visited_urls"

def is_visited(self, url):
    """检查URL是否可能已访问(可能有误判)"""
    return self.redis.execute_command("BF.EXISTS", self.key, url)

def mark_visited(self, url):
    """标记URL为已访问"""
    self.redis.execute_command("BF.ADD", self.key, url)

示例用法

bloom_deduper = RedisBloomFilterDedupe()
url = "https://example.com/page1"

if not bloom_deduper.is_visited(url):
bloom_deduper.mark_visited(url)
print(f"抓取: {url}")
else:
print(f"可能已访问: {url}")
优点:
● 内存占用低,误判率可控。
● 适用于海量URL去重。
缺点:
● 需要额外安装RedisBloom模块。

  1. 性能优化与对比
    方法 准确率 内存占用 适用场景
    Redis Set 100% 高 中小规模爬虫(<1000万URL)
    Redis HyperLogLog ~99.2% 极低 超大规模爬虫(允许少量误判)
    Redis Bloom Filter 可调 中 海量URL(需额外模块)
    优化建议:
  2. 短URL优化:存储URL的MD5或SHA1哈希值(减少内存占用)。
  3. 分片存储:按域名或哈希分片,避免单个Key过大。
  4. TTL过期:设置过期时间,避免长期累积无用URL。
  5. 结论
    在分布式爬虫中,Redis 是URL去重的理想选择,支持多种数据结构:
    ● 精确去重 → Redis Set
    ● 低内存消耗 → HyperLogLog
    ● 可控误判率 → Bloom Filter
    通过合理选择方案,可以显著提升爬虫效率,避免重复抓取。本文提供的Python代码可直接集成到Scrapy或其他爬虫框架中,助力高效数据采集。
相关文章
|
2月前
|
数据采集 测试技术 C++
无headers爬虫 vs 带headers爬虫:Python性能对比
无headers爬虫 vs 带headers爬虫:Python性能对比
|
3月前
|
数据采集 存储 数据可视化
分布式爬虫框架Scrapy-Redis实战指南
本文介绍如何使用Scrapy-Redis构建分布式爬虫系统,采集携程平台上热门城市的酒店价格与评价信息。通过代理IP、Cookie和User-Agent设置规避反爬策略,实现高效数据抓取。结合价格动态趋势分析,助力酒店业优化市场策略、提升服务质量。技术架构涵盖Scrapy-Redis核心调度、代理中间件及数据解析存储,提供完整的技术路线图与代码示例。
321 0
分布式爬虫框架Scrapy-Redis实战指南
|
1月前
|
数据采集 存储 NoSQL
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
基于Scrapy-Redis的分布式景点数据爬取与热力图生成
175 67
|
20天前
|
NoSQL 算法 安全
redis分布式锁在高并发场景下的方案设计与性能提升
本文探讨了Redis分布式锁在主从架构下失效的问题及其解决方案。首先通过CAP理论分析,Redis遵循AP原则,导致锁可能失效。针对此问题,提出两种解决方案:Zookeeper分布式锁(追求CP一致性)和Redlock算法(基于多个Redis实例提升可靠性)。文章还讨论了可能遇到的“坑”,如加从节点引发超卖问题、建议Redis节点数为奇数以及持久化策略对锁的影响。最后,从性能优化角度出发,介绍了减少锁粒度和分段锁的策略,并结合实际场景(如下单重复提交、支付与取消订单冲突)展示了分布式锁的应用方法。
86 3
|
30天前
|
缓存 监控 NoSQL
Redis设计与实现——分布式Redis
Redis Sentinel 和 Cluster 是 Redis 高可用与分布式架构的核心组件。Sentinel 提供主从故障检测与自动切换,通过主观/客观下线判断及 Raft 算法选举领导者完成故障转移,但存在数据一致性和复杂度问题。Cluster 支持数据分片和水平扩展,基于哈希槽分配数据,具备自动故障转移和节点发现机制,适合大规模高并发场景。复制机制包括全量同步和部分同步,通过复制积压缓冲区优化同步效率,但仍面临延迟和资源消耗挑战。两者各有优劣,需根据业务需求选择合适方案。
|
2月前
|
数据采集 存储 监控
Python 原生爬虫教程:网络爬虫的基本概念和认知
网络爬虫是一种自动抓取互联网信息的程序,广泛应用于搜索引擎、数据采集、新闻聚合和价格监控等领域。其工作流程包括 URL 调度、HTTP 请求、页面下载、解析、数据存储及新 URL 发现。Python 因其丰富的库(如 requests、BeautifulSoup、Scrapy)和简洁语法成为爬虫开发的首选语言。然而,在使用爬虫时需注意法律与道德问题,例如遵守 robots.txt 规则、控制请求频率以及合法使用数据,以确保爬虫技术健康有序发展。
244 31
|
20天前
|
存储 NoSQL Java
从扣减库存场景来讲讲redis分布式锁中的那些“坑”
本文从一个简单的库存扣减场景出发,深入分析了高并发下的超卖问题,并逐步优化解决方案。首先通过本地锁解决单机并发问题,但集群环境下失效;接着引入Redis分布式锁,利用SETNX命令实现加锁,但仍存在死锁、锁过期等隐患。文章详细探讨了通过设置唯一标识、续命机制等方法完善锁的可靠性,并最终引出Redisson工具,其内置的锁续命和原子性操作极大简化了分布式锁的实现。最后,作者剖析了Redisson源码,揭示其实现原理,并预告后续关于主从架构下分布式锁的应用与性能优化内容。
65 0
|
3月前
|
数据采集 监控 Python
Python爬虫异常处理:自动跳过无效URL
Python爬虫异常处理:自动跳过无效URL
Python爬虫异常处理:自动跳过无效URL
|
2月前
|
数据采集 XML 存储
Headers池技术在Python爬虫反反爬中的应用
Headers池技术在Python爬虫反反爬中的应用
|
3月前
|
机器学习/深度学习 存储 设计模式
Python 高级编程与实战:深入理解性能优化与调试技巧
本文深入探讨了Python的性能优化与调试技巧,涵盖profiling、caching、Cython等优化工具,以及pdb、logging、assert等调试方法。通过实战项目,如优化斐波那契数列计算和调试Web应用,帮助读者掌握这些技术,提升编程效率。附有进一步学习资源,助力读者深入学习。

推荐镜像

更多