Python爬虫去重策略:增量爬取与历史数据比对

本文涉及的产品
实时计算 Flink 版,1000CU*H 3个月
智能开放搜索 OpenSearch行业算法版,1GB 20LCU 1个月
实时数仓Hologres,5000CU*H 100GB 3个月
简介: Python爬虫去重策略:增量爬取与历史数据比对
  1. 引言
    在数据采集过程中,爬虫经常需要面对 重复数据 的问题。如果每次爬取都全量抓取,不仅浪费资源,还可能导致数据冗余。增量爬取(Incremental Crawling) 是一种高效策略,它仅抓取 新增或更新 的数据,而跳过已采集的旧数据。
    本文将详细介绍 Python爬虫的增量爬取与历史数据比对 策略,涵盖以下内容:
  2. 增量爬取的核心思路
  3. 去重方案对比(数据库、文件、内存)
  4. 基于时间戳、哈希、数据库比对的实现方法
  5. 完整代码示例(Scrapy + MySQL 增量爬取)
  6. 增量爬取的核心思路
    增量爬取的核心是 识别哪些数据是新的或已更新的,通常采用以下方式:
    ● 基于时间戳(Last-Modified / Update-Time)
    ● 基于内容哈希(MD5/SHA1)
    ● 基于数据库比对(MySQL/Redis/MongoDB)
    2.1 基于时间戳的增量爬取
    适用于数据源带有 发布时间(如新闻、博客) 的场景:
  7. 记录上次爬取的 最新时间戳
  8. 下次爬取时,只抓取 晚于该时间戳的数据
    优点:简单高效,适用于结构化数据
    缺点:依赖数据源的时间字段,不适用于无时间戳的网页
    2.2 基于内容哈希的去重
    适用于 内容可能更新但URL不变 的页面(如电商价格):
  9. 计算页面内容的 哈希值(如MD5)
  10. 比对哈希值,若变化则视为更新
    优点:适用于动态内容
    缺点:计算开销较大
    2.3 基于数据库比对的增量爬取
    适用于 大规模数据管理:
  11. 将已爬取的 URL 或关键字段 存入数据库(MySQL/Redis)
  12. 每次爬取前查询数据库,判断是否已存在
    优点:支持分布式去重
    缺点:需要额外存储
  13. 去重方案对比
    方案 适用场景 优点 缺点
    内存去重 单机小规模爬虫 速度快(set()
    ) 重启后数据丢失
    文件存储 中小规模爬虫 简单(CSV/JSON) 性能较低
    SQL数据库 结构化数据管理 支持复杂查询(MySQL) 需要数据库维护
    NoSQL数据库 高并发分布式爬虫 高性能(Redis/MongoDB) 内存占用较高
  14. 增量爬取实现方法
    4.1 基于时间戳的增量爬取(示例)
    import scrapy
    from datetime import datetime

class NewsSpider(scrapy.Spider):
name = "news_spider"
last_crawl_time = None # 上次爬取的最新时间

def start_requests(self):
    # 从文件/DB加载上次爬取时间
    self.last_crawl_time = self.load_last_crawl_time()

    # 设置代理信息
    proxy = "http://www.16yun.cn:5445"
    proxy_auth = "16QMSOML:280651"

    # 添加代理到请求中
    yield scrapy.Request(
        url="https://news.example.com/latest",
        meta={
            'proxy': proxy,
            'proxy_user_pass': proxy_auth
        }
    )

def parse(self, response):
    # 检查响应状态码,判断是否成功获取数据
    if response.status != 200:
        self.logger.error(f"Failed to fetch data from {response.url}. Status code: {response.status}")
        self.logger.error("This might be due to network issues or an invalid URL. Please check the URL and try again.")
        return

    for article in response.css(".article"):
        pub_time = datetime.strptime(
            article.css(".time::text").get(), 
            "%Y-%m-%d %H:%M:%S"
        )
        if self.last_crawl_time and pub_time <= self.last_crawl_time:
            continue  # 跳过旧文章

        yield {
            "title": article.css("h2::text").get(),
            "time": pub_time,
        }

    # 更新最新爬取时间
    self.save_last_crawl_time(datetime.now())

def load_last_crawl_time(self):
    try:
        with open("last_crawl.txt", "r") as f:
            return datetime.strptime(f.read(), "%Y-%m-%d %H:%M:%S")
    except FileNotFoundError:
        return None

def save_last_crawl_time(self, time):
    with open("last_crawl.txt", "w") as f:
        f.write(time.strftime("%Y-%m-%d %H:%M:%S"))

4.2 基于内容哈希的去重(示例)
import hashlib

class ContentHashSpider(scrapy.Spider):
name = "hash_spider"
seen_hashes = set() # 存储已爬取的哈希

def parse(self, response):
    content = response.css("body").get()
    content_hash = hashlib.md5(content.encode()).hexdigest()

    if content_hash in self.seen_hashes:
        return  # 跳过重复内容

    self.seen_hashes.add(content_hash)
    yield {"url": response.url, "content": content}

4.3 基于MySQL的增量爬取(完整示例)
(1)MySQL 表结构
CREATE TABLE crawled_data (
id INT AUTO_INCREMENT PRIMARY KEY,
url VARCHAR(255) UNIQUE,
content_hash CHAR(32),
last_updated TIMESTAMP
);
(2)Scrapy 爬虫代码
import pymysql
import hashlib
from scrapy import Spider, Request

class MySQLIncrementalSpider(Spider):
name = "mysql_incremental"
start_urls = ["https://example.com"]

def __init__(self):
    self.conn = pymysql.connect(
        host="localhost",
        user="root",
        password="123456",
        db="crawler_db"
    )
    self.cursor = self.conn.cursor()

def parse(self, response):
    url = response.url
    content = response.text
    content_hash = hashlib.md5(content.encode()).hexdigest()

    # 检查是否已爬取
    self.cursor.execute(
        "SELECT content_hash FROM crawled_data WHERE url=%s",
        (url,)
    )
    result = self.cursor.fetchone()

    if result and result[0] == content_hash:
        return  # 内容未更新

    # 插入或更新数据库
    self.cursor.execute(
        """INSERT INTO crawled_data (url, content_hash, last_updated)
           VALUES (%s, %s, NOW())
           ON DUPLICATE KEY UPDATE 
           content_hash=%s, last_updated=NOW()""",
        (url, content_hash, content_hash)
    )
    self.conn.commit()

    yield {"url": url, "content": content}

def close(self, reason):
    self.cursor.close()
    self.conn.close()
  1. 结论
    策略 适用场景 推荐存储方案
    时间戳比对 新闻、博客等带时间的数据 文件/MySQL
    内容哈希 动态内容(如商品价格) Redis/内存
    数据库去重 结构化数据管理 MySQL/MongoDB
    最佳实践:
    ● 小型爬虫 → 内存去重(set())
    ● 中型爬虫 → 文件存储(JSON/CSV)
    ● 大型分布式爬虫 → Redis + MySQL
    通过合理选择增量爬取策略,可以显著提升爬虫效率,减少资源浪费。
相关文章
|
5天前
|
数据采集 Web App开发 数据可视化
Python零基础爬取东方财富网股票行情数据指南
东方财富网数据稳定、反爬宽松,适合爬虫入门。本文详解使用Python抓取股票行情数据,涵盖请求发送、HTML解析、动态加载处理、代理IP切换及数据可视化,助你快速掌握金融数据爬取技能。
110 1
|
16天前
|
数据采集 Web App开发 自然语言处理
新闻热点一目了然:Python爬虫数据可视化
新闻热点一目了然:Python爬虫数据可视化
|
6天前
|
Java 数据处理 索引
(Pandas)Python做数据处理必选框架之一!(二):附带案例分析;刨析DataFrame结构和其属性;学会访问具体元素;判断元素是否存在;元素求和、求标准值、方差、去重、删除、排序...
DataFrame结构 每一列都属于Series类型,不同列之间数据类型可以不一样,但同一列的值类型必须一致。 DataFrame拥有一个总的 idx记录列,该列记录了每一行的索引 在DataFrame中,若列之间的元素个数不匹配,且使用Series填充时,在DataFrame里空值会显示为NaN;当列之间元素个数不匹配,并且不使用Series填充,会报错。在指定了index 属性显示情况下,会按照index的位置进行排序,默认是 [0,1,2,3,...] 从0索引开始正序排序行。
59 0
|
6天前
|
Java 数据挖掘 数据处理
(Pandas)Python做数据处理必选框架之一!(一):介绍Pandas中的两个数据结构;刨析Series:如何访问数据;数据去重、取众数、总和、标准差、方差、平均值等;判断缺失值、获取索引...
Pandas 是一个开源的数据分析和数据处理库,它是基于 Python 编程语言的。 Pandas 提供了易于使用的数据结构和数据分析工具,特别适用于处理结构化数据,如表格型数据(类似于Excel表格)。 Pandas 是数据科学和分析领域中常用的工具之一,它使得用户能够轻松地从各种数据源中导入数据,并对数据进行高效的操作和分析。 Pandas 主要引入了两种新的数据结构:Series 和 DataFrame。
114 0
|
14天前
|
数据采集 监控 数据库
Python异步编程实战:爬虫案例
🌟 蒋星熠Jaxonic,代码为舟的星际旅人。从回调地狱到async/await协程天堂,亲历Python异步编程演进。分享高性能爬虫、数据库异步操作、限流监控等实战经验,助你驾驭并发,在二进制星河中谱写极客诗篇。
Python异步编程实战:爬虫案例
|
16天前
|
数据采集 存储 XML
Python爬虫技术:从基础到实战的完整教程
最后强调: 父母法律法规限制下进行网络抓取活动; 不得侵犯他人版权隐私利益; 同时也要注意个人安全防止泄露敏感信息.
445 19
|
7天前
|
JSON API 数据安全/隐私保护
Python采集淘宝拍立淘按图搜索API接口及JSON数据返回全流程指南
通过以上流程,可实现淘宝拍立淘按图搜索的完整调用链路,并获取结构化的JSON商品数据,支撑电商比价、智能推荐等业务场景。
|
15天前
|
数据采集 关系型数据库 MySQL
python爬取数据存入数据库
Python爬虫结合Scrapy与SQLAlchemy,实现高效数据采集并存入MySQL/PostgreSQL/SQLite。通过ORM映射、连接池优化与批量提交,支持百万级数据高速写入,具备良好的可扩展性与稳定性。
|
26天前
|
JSON API 数据安全/隐私保护
Python采集淘宝评论API接口及JSON数据返回全流程指南
Python采集淘宝评论API接口及JSON数据返回全流程指南
|
28天前
|
数据采集 数据可视化 关系型数据库
基于python大数据的电影数据可视化分析系统
电影分析与可视化平台顺应电影产业数字化趋势,整合大数据处理、人工智能与Web技术,实现电影数据的采集、分析与可视化展示。平台支持票房、评分、观众行为等多维度分析,助力行业洞察与决策,同时提供互动界面,增强观众对电影文化的理解。技术上依托Python、MySQL、Flask、HTML等构建,融合数据采集与AI分析,提升电影行业的数据应用能力。

推荐镜像

更多