Python爬虫数据加密存储实战:AES-256-GCM与cryptography库应用
1. 项目概述为什么爬虫数据需要加密存储做爬虫的朋友尤其是处理过一些敏感数据比如用户评论、商品价格、甚至是公开但涉及隐私边界的公开信息的应该都遇到过这样一个问题爬下来的数据就这么直接扔在本地文件或者数据库里真的安全吗我刚开始做爬虫那会儿也觉得数据放自己电脑上能有什么风险。直到有一次一个存放了数十万条用户公开联系方式的CSV文件因为误操作被同步到了网盘虽然最后没造成实际损失但那次冷汗直流的经历让我彻底改变了看法。数据安全从来都不是“我觉得应该没事”就能保证的。你的爬虫脚本可能因为版本管理工具如Git的.gitignore配置疏忽而泄露你的开发环境可能被恶意软件扫描甚至你只是简单地把数据文件通过聊天软件发给同事审查都可能存在中间环节被截获的风险。更不用说如果你爬取的数据本身具有一定的商业价值或敏感性明文存储简直就是为数据泄露敞开了大门。因此“加密存储与解密读取”不是一个炫技的附加功能而是爬虫工程化、合规化进程中必须考虑的一环。它核心解决两个问题一是静态存储安全确保数据在硬盘上即使被直接访问也无法被轻易解读二是传输与使用安全在数据需要移动、共享或在非受控环境中使用时提供一层保护。本次实战我们就来深入聊聊如何用Python为你的爬虫数据穿上“盔甲”。2. 核心思路与方案选型给数据加密听起来高大上其实思路很直接在数据写入磁盘前用一把“钥匙”密钥把它搅乱变成一堆乱码需要读取时再用同一把钥匙把它恢复原样。关键在于如何选择这把“钥匙”和“搅乱”的算法。2.1 加密算法选型对称加密是首选对于爬虫数据的存储加密对称加密算法是几乎唯一的选择。原因很简单加密和解密使用同一个密钥速度快、效率高非常适合处理可能海量的文本或结构化数据。非对称加密如RSA通常用于密钥交换或数字签名加解密大数据性能是瓶颈。在对称加密算法中我们主要有以下选择AES (Advanced Encryption Standard)目前国际通用的加密标准安全性和性能俱佳。支持128、192、256位密钥长度。对于爬虫数据AES-256能提供军用级别的安全强度且现代CPU通常都有对其的硬件加速支持速度非常快。DES / 3DES已经过时或不推荐使用。DES密钥长度短56位已被证明不安全3DES速度慢且逐渐被淘汰。ChaCha20一种较新的流密码在某些平台上特别是没有AES硬件加速的移动设备可能比AES更快。但在Python生态和通用服务器场景下AES的支持更成熟、更广泛。结论对于绝大多数Python爬虫项目选择AES-256作为加密算法是最稳妥、最通用的方案。Python的cryptography库提供了生产级的安全实现。2.2 加密模式与填充选定了AES还没完。AES是一个分组密码它一次处理一个固定长度128位即16字节的数据块。我们的数据长度不可能总是16字节的整数倍这就需要“填充”Padding。同时如何将多个数据块关联起来加密就是“模式”Mode。模式选择ECB (Electronic Codebook)绝对不要用相同的明文块会被加密成相同的密文块会泄露数据模式安全性极差。CBC (Cipher Block Chaining)最常用的模式之一。每个明文块先与前一个密文块进行异或操作后再加密。需要一个**初始化向量IV**来加密第一个块。IV不需要保密但必须不可预测通常随机生成且每次加密都应使用不同的IV。GCM (Galois/Counter Mode)推荐模式。它同时提供了加密和完整性认证防止密文被篡改。相比CBC它通常更高效且不需要填充。cryptography库对其有良好支持。填充选择如果使用CBC等需要填充的模式常用PKCS7填充。实操心得如果库支持优先使用 AES-256-GCM。它解决了加密和认证且无需处理填充问题更简单安全。如果环境限制必须用CBC务必确保每次加密使用随机生成的IV并将IV与密文一起存储。2.3 密钥管理安全的核心“钥匙”放在哪是整个方案最脆弱的一环。你不能把密钥硬编码在脚本里那和明文存储没区别。环境变量最基础、推荐的方式。将密钥以字符串形式设置在操作系统的环境变量中脚本运行时读取。# 在终端中设置临时 export MY_SCRAPER_SECRET_KEYyour-32-byte-secret-key-here在Python中读取import os key os.environ.get(MY_SCRAPER_SECRET_KEY) if not key: raise ValueError(加密密钥未在环境变量中设置) # 确保密钥是字节类型且长度正确AES-256需要32字节 key_bytes key.encode(utf-8) if len(key_bytes) ! 32: raise ValueError(密钥必须为32字节256位)配置文件.env文件使用python-dotenv库管理。将密钥写在项目根目录的.env文件里切记加入.gitignore脚本加载该文件。# .env 文件 SCRAPER_SECRET_KEYyour-32-byte-secret-key-herefrom dotenv import load_dotenv load_dotenv() # 加载 .env 文件中的变量到环境变量 key os.environ.get(SCRAPER_SECRET_KEY)密钥管理服务KMS在生产环境或团队协作中考虑使用云服务商如AWS KMS, GCP Secret Manager或专门的密钥管理工具如HashiCorp Vault。这些服务提供密钥的轮换、审计和更精细的访问控制。注意事项密钥本身需要是足够随机的字节序列。你可以用os.urandom(32)生成一个然后将其进行Base64编码再存入环境变量。绝对不要使用“password123”或“mysecretkey”这种弱密钥。2.4 数据序列化格式加密操作的对象是字节bytes。我们爬取的数据通常是字典、列表等结构。因此在加密前需要序列化解密后需要反序列化。JSON最通用。json.dumps()生成字符串再编码为字节。json.loads()进行反向操作。适合大多数结构化数据。PicklePython专属可以序列化几乎任何Python对象包括自定义类实例。但存在安全风险如果反序列化来源不可信的pickle数据可能导致任意代码执行。仅在你完全信任数据源且需要保存复杂对象时使用。MessagePack / CBOR二进制序列化格式比JSON更紧凑序列化/反序列化速度更快。如果数据量极大考虑使用。个人选择对于爬虫数据存储JSON通常是首选。它人类可读在加密前调试方便、跨语言、安全。只有在极端追求性能或存储空间时才考虑二进制格式。3. 核心实现基于 cryptography 库的完整流程我们选择cryptography库因为它是一个被广泛审计、维护活跃、提供“安全默认值”的库比PyCrypto或早期的PyCryptodome更推荐。3.1 安装与基础准备首先安装库pip install cryptography然后准备我们的核心工具类。我们将实现两种模式AES-GCM推荐和AES-CBC备选。import os import json from base64 import b64encode, b64decode from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.primitives import padding from cryptography.hazmat.backends import default_backend import secrets class DataCryptoManager: 爬虫数据加密管理器 def __init__(self, key: bytes): 初始化加密管理器。 :param key: 加密密钥必须是字节类型。 AES-256-GCM 和 AES-256-CBC 均需要32字节密钥。 if len(key) not in [16, 24, 32]: raise ValueError(密钥长度必须为16(AES-128), 24(AES-192)或32(AES-256)字节) self.key key self.backend default_backend()3.2 方案一使用 AES-GCM 模式加密/解密推荐GCM模式将加密和认证标签Tag生成结合在一起。解密时需要提供Tag进行验证。def encrypt_gcm(self, plaintext_data: dict) - dict: 使用 AES-GCM 模式加密数据。 :param plaintext_data: 待加密的Python字典数据。 :return: 一个字典包含加密后的数据、IV和认证标签。 # 1. 序列化数据为JSON字符串再转为字节 plaintext_bytes json.dumps(plaintext_data).encode(utf-8) # 2. 生成随机IV对于GCM通常称为nonce推荐12字节 iv secrets.token_bytes(12) # 3. 构建加密器 encryptor Cipher( algorithms.AES(self.key), modes.GCM(iv), backendself.backend ).encryptor() # 4. 加密数据并生成Tag ciphertext_bytes encryptor.update(plaintext_bytes) encryptor.finalize() tag encryptor.tag # 5. 将IV、密文、Tag一起Base64编码方便存储例如存JSON encrypted_package { iv: b64encode(iv).decode(utf-8), ciphertext: b64encode(ciphertext_bytes).decode(utf-8), tag: b64encode(tag).decode(utf-8), mode: GCM # 记录模式便于后续解密判断 } return encrypted_package def decrypt_gcm(self, encrypted_package: dict) - dict: 解密由 encrypt_gcm 生成的数据包。 :param encrypted_package: 包含 iv, ciphertext, tag, mode 的字典。 :return: 解密后的原始Python字典数据。 if encrypted_package.get(mode) ! GCM: raise ValueError(数据包加密模式不是GCM无法解密) # 1. 从数据包中解码出原始字节 iv b64decode(encrypted_package[iv]) ciphertext_bytes b64decode(encrypted_package[ciphertext]) tag b64decode(encrypted_package[tag]) # 2. 构建解密器传入IV和Tag decryptor Cipher( algorithms.AES(self.key), modes.GCM(iv, tag), backendself.backend ).decryptor() # 3. 解密数据 plaintext_bytes decryptor.update(ciphertext_bytes) decryptor.finalize() # 4. 反序列化JSON字节为Python字典 plaintext_data json.loads(plaintext_bytes.decode(utf-8)) return plaintext_dataGCM模式优点一次调用完成加密和认证。无需处理数据填充。认证标签Tag可以防止密文在存储后被篡改。3.3 方案二使用 AES-CBC 模式加密/解密备选如果你的运行环境因某些原因无法使用GCMCBC是可靠的备选方案。def encrypt_cbc(self, plaintext_data: dict) - dict: 使用 AES-CBC 模式加密数据。 :param plaintext_data: 待加密的Python字典数据。 :return: 一个字典包含加密后的数据和IV。 # 1. 序列化数据为JSON字节 plaintext_bytes json.dumps(plaintext_data).encode(utf-8) # 2. 使用PKCS7填充使数据长度为16字节的倍数 padder padding.PKCS7(algorithms.AES.block_size).padder() padded_data padder.update(plaintext_bytes) padder.finalize() # 3. 生成随机IV16字节 iv secrets.token_bytes(16) # 4. 构建加密器并加密 encryptor Cipher( algorithms.AES(self.key), modes.CBC(iv), backendself.backend ).encryptor() ciphertext_bytes encryptor.update(padded_data) encryptor.finalize() # 5. 打包数据 encrypted_package { iv: b64encode(iv).decode(utf-8), ciphertext: b64encode(ciphertext_bytes).decode(utf-8), mode: CBC } return encrypted_package def decrypt_cbc(self, encrypted_package: dict) - dict: 解密由 encrypt_cbc 生成的数据包。 :param encrypted_package: 包含 iv, ciphertext, mode 的字典。 :return: 解密后的原始Python字典数据。 if encrypted_package.get(mode) ! CBC: raise ValueError(数据包加密模式不是CBC无法解密) # 1. 解码 iv b64decode(encrypted_package[iv]) ciphertext_bytes b64decode(encrypted_package[ciphertext]) # 2. 构建解密器并解密 decryptor Cipher( algorithms.AES(self.key), modes.CBC(iv), backendself.backend ).decryptor() padded_plaintext_bytes decryptor.update(ciphertext_bytes) decryptor.finalize() # 3. 去除PKCS7填充 unpadder padding.PKCS7(algorithms.AES.block_size).unpadder() plaintext_bytes unpadder.update(padded_plaintext_bytes) unpadder.finalize() # 4. 反序列化 plaintext_data json.loads(plaintext_bytes.decode(utf-8)) return plaintext_dataCBC模式注意事项IV必须随机且唯一每次加密都必须使用新的随机IV绝对不能重用。重用的IV会严重破坏安全性。需要填充PKCS7填充是标准做法。不提供完整性校验CBC本身不验证密文是否被篡改。如果担心数据完整性需要额外计算并存储HMAC。3.4 集成到爬虫流程存储与读取现在我们将加密管理器集成到一个模拟的爬虫流程中。def main(): # --- 密钥管理示例从环境变量获取--- import os # 假设你的密钥已通过环境变量 SCRAPER_AES_KEY 设置且是32字节的Base64编码字符串 # 生成密钥的命令python -c import os; import base64; print(base64.b64encode(os.urandom(32)).decode()) key_base64 os.environ.get(SCRAPER_AES_KEY) if not key_base64: print(错误未设置环境变量 SCRAPER_AES_KEY) return KEY b64decode(key_base64) # 解码为原始字节 # 初始化加密管理器 crypto_mgr DataCryptoManager(KEY) # --- 模拟爬虫数据 --- scraped_data { url: https://example.com/item/123, title: Python编程从入门到实践, price: 89.90, stock: True, comments: [好书推荐, 适合初学者], timestamp: 2023-10-27T10:30:00Z } print(原始数据:, scraped_data) # --- 加密并存储到文件使用GCM模式--- encrypted_package crypto_mgr.encrypt_gcm(scraped_data) # 将加密后的包保存为JSON文件 import json with open(encrypted_data.json, w, encodingutf-8) as f: json.dump(encrypted_package, f, indent2) print(数据已加密存储至 encrypted_data.json) print(加密后数据包结构:, encrypted_package.keys()) # --- 从文件读取并解密 --- with open(encrypted_data.json, r, encodingutf-8) as f: loaded_package json.load(f) # 根据数据包中的模式字段选择解密方法 if loaded_package.get(mode) GCM: decrypted_data crypto_mgr.decrypt_gcm(loaded_package) elif loaded_package.get(mode) CBC: decrypted_data crypto_mgr.decrypt_cbc(loaded_package) else: raise ValueError(未知的加密模式) print(解密后数据:, decrypted_data) print(数据比对结果:, scraped_data decrypted_data) if __name__ __main__: main()运行这段代码你会看到加密后的encrypted_data.json文件内容大致如下{ iv: L5Xp7v2k1eMq9gTd, ciphertext: 9Hj3n...很长一串Base64..., tag: cXJp8...另一串Base64..., mode: GCM }iv和tag是公开的但没有密钥KEY任何人都无法从ciphertext中恢复出原始数据。4. 进阶话题与性能优化4.1 加密大型数据集或流式数据上面的例子加密的是单个字典对象。如果你爬取的是百万级的数据条目全部加载到内存再加密显然不现实。这时需要流式或分块处理。思路将数据分批次例如每1000条记录序列化为JSON字符串然后加密并将每个加密后的数据包追加到文件或存入数据库的某个字段。读取时也分批解密。def encrypt_large_dataset(data_iterator, crypto_mgr, output_file_path, batch_size1000): 流式加密大型数据集。 :param data_iterator: 生成器或迭代器每次 yield 一批数据列表。 :param crypto_mgr: DataCryptoManager 实例。 :param output_file_path: 输出文件路径。 :param batch_size: 每批处理的数据条数。 import json encrypted_chunks [] for batch in data_iterator: # 假设 batch 是一个字典列表 plaintext_bytes json.dumps(batch).encode(utf-8) encrypted_package crypto_mgr.encrypt_gcm({data: batch}) # 包装一下 encrypted_chunks.append(encrypted_package) # 可以每加密N批就写入一次文件避免内存占用过大 if len(encrypted_chunks) 10: _append_to_file(encrypted_chunks, output_file_path) encrypted_chunks [] if encrypted_chunks: _append_to_file(encrypted_chunks, output_file_path) def _append_to_file(chunks, filepath): 将加密数据块追加到文件每行一个JSON with open(filepath, a, encodingutf-8) as f: for chunk in chunks: f.write(json.dumps(chunk) \n) # 使用换行符分隔对应的解密读取函数则需要逐行读取、解析JSON、解密。4.2 数据库存储集成更常见的场景是将加密后的数据存入数据库如SQLite, MySQL, MongoDB。原则是将序列化加密后的字节数据以BLOB二进制大对象或TEXTBase64编码后的字符串格式存储。以SQLite为例import sqlite3 import json def save_encrypted_to_db(db_path, item_id, plaintext_data, crypto_mgr): conn sqlite3.connect(db_path) cursor conn.cursor() # 创建表如果不存在 cursor.execute( CREATE TABLE IF NOT EXISTS scraped_data ( id TEXT PRIMARY KEY, encrypted_content TEXT NOT NULL, -- 存储Base64编码后的加密包JSON字符串 created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ) ) # 加密数据 encrypted_package crypto_mgr.encrypt_gcm(plaintext_data) encrypted_json_str json.dumps(encrypted_package) # 插入数据库 cursor.execute( INSERT OR REPLACE INTO scraped_data (id, encrypted_content) VALUES (?, ?) , (item_id, encrypted_json_str)) conn.commit() conn.close() def read_decrypted_from_db(db_path, item_id, crypto_mgr): conn sqlite3.connect(db_path) cursor conn.cursor() cursor.execute(SELECT encrypted_content FROM scraped_data WHERE id ?, (item_id,)) row cursor.fetchone() conn.close() if row: encrypted_package json.loads(row[0]) return crypto_mgr.decrypt_gcm(encrypted_package) return None注意事项数据库字段类型选择TEXT存储JSON字符串或BLOB直接存储加密后的字节。TEXT更通用便于调试。如果数据量极大考虑对加密后的ciphertext字段进行压缩如使用zlib再存入数据库以节省空间。确保数据库连接本身是安全的如使用SSL防止网络嗅探。4.3 性能考量与实测加密/解密是CPU密集型操作。对于海量数据爬取需要评估性能影响。基准测试使用timeit模块测试加密一条典型数据如1KB的JSON所需时间。异步处理如果爬虫是异步的如使用asyncioaiohttp加密/解密操作是CPU阻塞的会阻塞事件循环。建议将加密/解密操作放入线程池中执行避免影响网络IO并发。import asyncio from concurrent.futures import ThreadPoolExecutor executor ThreadPoolExecutor(max_workers4) # 根据CPU核心数调整 async def crawl_and_store(url, crypto_mgr): data await fetch_url(url) # 异步获取数据 # 将CPU密集的加密操作放到线程池 loop asyncio.get_event_loop() encrypted_package await loop.run_in_executor( executor, crypto_mgr.encrypt_gcm, data ) await save_to_db_async(encrypted_package) # 异步存储选择性加密并非所有字段都需要加密。例如URL、时间戳等公开信息可以明文存储只有价格、评论内容等敏感字段加密。这能显著减少需要加密的数据量。但实现更复杂需要定义字段级别的加密策略。5. 常见问题、排查与安全强化5.1 常见错误与排查错误现象可能原因解决方案ValueError: Invalid key size密钥长度不是16/24/32字节。检查密钥来源。如果是环境变量确保读取后解码成字节的长度正确。用len(key)打印确认。cryptography.exceptions.InvalidTag(GCM模式)认证标签验证失败。1. 密文或Tag在存储/传输中被篡改。2. 解密时使用的密钥与加密时不同。3. IV/Tag与密文不匹配数据包损坏。检查数据完整性。ValueError: Invalid padding bytes(CBC模式)PKCS7填充验证失败。1. 解密密钥错误导致解密出的明文字节无效。2. 密文损坏。3. 加密和解密使用的IV不一致。解密后JSON解析错误解密成功但得到乱码。几乎可以肯定是密钥错误。解密过程没有报错因为任何字节都能被“解密”但得到的是无意义的字节无法被json.loads()解析。性能瓶颈加密大量小数据包。考虑将多条数据合并成一个列表或字典进行批量加密减少加密操作的调用次数和序列化开销。5.2 安全强化建议密钥轮换定期如每季度更换加密密钥。对于新数据使用新密钥加密。旧数据可以保留用旧密钥解密后再用新密钥加密或者维护一个密钥版本映射表。加密算法升级关注cryptography库和安全社区的动态。如果AES-GCM在未来被发现弱点应有计划地迁移到更安全的算法。完整性校验CBC模式如果使用CBC模式强烈建议结合HMACHash-based Message Authentication Code来验证数据完整性。流程是加密后对IV 密文计算HMAC存储密文、IV和HMAC值。读取时先验证HMAC再解密。from cryptography.hazmat.primitives import hashes, hmac def encrypt_cbc_with_hmac(data, key, hmac_key): # ... 加密过程得到 iv 和 ciphertext ... # 计算HMAC h hmac.HMAC(hmac_key, hashes.SHA256()) h.update(iv ciphertext) hmac_digest h.finalize() # 存储 iv, ciphertext, hmac_digest注意HMAC密钥必须与加密密钥不同。访问日志与审计记录数据解密访问的日志谁、何时、访问了哪条数据便于事后审计。防范内存泄露密钥和明文数据在内存中。确保程序结束时妥善清理。对于特别敏感的数据可以考虑使用ctypes的memset手动覆盖内存中的密钥字节数组尽管Python的垃圾回收机制使得这并不绝对可靠。5.3 一个完整的、生产可用的示例脚本最后我将一个整合了环境变量管理、GCM加密、文件存储、错误处理和安全建议的脚本框架分享出来你可以直接以此为模板开始你的项目。#!/usr/bin/env python3 安全爬虫数据存储模块 使用 AES-256-GCM 加密密钥通过环境变量管理。 import os import json import sys from base64 import b64encode, b64decode from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes from cryptography.hazmat.backends import default_backend from cryptography.exceptions import InvalidTag import secrets import logging logging.basicConfig(levellogging.INFO, format%(asctime)s - %(levelname)s - %(message)s) logger logging.getLogger(__name__) class SecureStorage: 安全存储核心类 def __init__(self, key_env_varSCRAPER_SECRET_KEY): 从环境变量初始化密钥。 :param key_env_var: 存储Base64编码密钥的环境变量名。 key_b64 os.environ.get(key_env_var) if not key_b64: logger.error(f环境变量 {key_env_var} 未设置。) logger.info(请通过以下命令生成并设置密钥) logger.info( python -c \import os, base64; print(base64.b64encode(os.urandom(32)).decode(utf-8))\) sys.exit(1) try: self.key b64decode(key_b64) if len(self.key) ! 32: logger.error(f密钥长度错误。需要32字节实际得到{len(self.key)}字节。) sys.exit(1) except Exception as e: logger.error(f密钥解码失败: {e}) sys.exit(1) self.backend default_backend() logger.info(安全存储模块初始化成功。) def encrypt_data(self, plaintext_dict: dict) - dict: 加密Python字典数据。 try: plaintext_bytes json.dumps(plaintext_dict).encode(utf-8) iv secrets.token_bytes(12) # GCM推荐12字节nonce encryptor Cipher( algorithms.AES(self.key), modes.GCM(iv), backendself.backend ).encryptor() ciphertext_bytes encryptor.update(plaintext_bytes) encryptor.finalize() tag encryptor.tag return { iv: b64encode(iv).decode(utf-8), ciphertext: b64encode(ciphertext_bytes).decode(utf-8), tag: b64encode(tag).decode(utf-8), v: 1.0 # 版本号便于未来格式升级 } except Exception as e: logger.error(f数据加密失败: {e}) raise def decrypt_data(self, encrypted_package: dict) - dict: 解密数据包。 required_keys {iv, ciphertext, tag, v} if not required_keys.issubset(encrypted_package.keys()): logger.error(f数据包格式错误缺少必要字段。需要 {required_keys}) raise ValueError(无效的数据包格式) try: iv b64decode(encrypted_package[iv]) ciphertext_bytes b64decode(encrypted_package[ciphertext]) tag b64decode(encrypted_package[tag]) decryptor Cipher( algorithms.AES(self.key), modes.GCM(iv, tag), backendself.backend ).decryptor() plaintext_bytes decryptor.update(ciphertext_bytes) decryptor.finalize() return json.loads(plaintext_bytes.decode(utf-8)) except InvalidTag: logger.error(解密失败认证标签无效。数据可能被篡改或密钥错误。) raise except Exception as e: logger.error(f数据解密失败: {e}) raise def save_to_file(self, data: dict, filepath: str): 加密数据并保存到JSON文件。 encrypted self.encrypt_data(data) try: with open(filepath, w, encodingutf-8) as f: json.dump(encrypted, f, indent2, ensure_asciiFalse) logger.info(f数据已安全保存至: {filepath}) except IOError as e: logger.error(f写入文件失败: {e}) raise def load_from_file(self, filepath: str) - dict: 从JSON文件加载并解密数据。 try: with open(filepath, r, encodingutf-8) as f: encrypted json.load(f) decrypted self.decrypt_data(encrypted) logger.info(f数据已从 {filepath} 安全加载。) return decrypted except FileNotFoundError: logger.error(f文件不存在: {filepath}) raise except json.JSONDecodeError: logger.error(f文件不是有效的JSON: {filepath}) raise # 使用示例 if __name__ __main__: # 假设已设置环境变量export SCRAPER_SECRET_KEY你的32字节Base64密钥 storage SecureStorage() # 模拟爬取的数据 sample_data { id: product_001, name: 无线蓝牙耳机, attributes: {color: black, battery_life: 30h}, price_history: [199, 189, 179], crawled_at: 2023-10-27T14:00:00Z } # 加密保存 storage.save_to_file(sample_data, secure_product_data.json) # 解密读取 try: loaded_data storage.load_from_file(secure_product_data.json) print(解密成功数据内容:) print(json.dumps(loaded_data, indent2, ensure_asciiFalse)) assert sample_data loaded_data, 解密后数据与原始数据不一致 print(数据完整性验证通过) except Exception as e: print(f操作失败: {e})这个脚本提供了一个健壮的起点。记住安全是一个过程而不是一个状态。从为你的爬虫数据实施加密开始你就已经朝着更负责任的数据处理迈出了关键一步。在实际部署前务必在测试环境中充分验证整个流程。