SQLCipher实战指南:为SQLite数据库穿上加密盔甲
1. 项目概述为什么我们需要SQLCipher在移动应用和桌面软件开发的日常工作中数据安全是一个绕不开的话题。尤其是当你的应用需要处理用户敏感信息比如聊天记录、个人笔记、财务数据甚至是简单的登录凭证缓存时如何安全地存储这些数据就成了一个核心挑战。很多开发者尤其是刚入行的朋友可能会觉得“我把数据库文件放在应用私有目录不就行了”。这个想法在早期或许还凑合但随着用户安全意识的提升和设备越狱、Root的普遍存在仅仅依赖文件系统权限是远远不够的。一旦设备被破解你的数据库文件就像一本摊开的日记可以被任意读取和修改。这就是SQLCipher登场的时候。SQLCipher不是一个全新的数据库它是对我们熟悉的SQLite数据库引擎的一个扩展。简单来说它给SQLite穿上了“加密盔甲”。你依然使用标准的SQLite API进行增删改查但底层所有的数据包括数据库文件本身、日志文件、临时文件在写入磁盘前都会被自动加密。没有正确的密钥任何人拿到的都是一个无法解析的二进制乱码文件。我最早接触SQLCipher是在一个金融类App的项目中监管要求所有本地存储的用户数据必须加密。当时对比了几种方案最终选择了SQLCipher原因很简单它成熟、稳定并且与SQLite的兼容性做到了几乎无缝。这次我们就以SQLCipher 3.0.1这个经典版本为例深入聊聊它的实战应用从集成、配置到日常开发中的那些“坑”和技巧。2. SQLCipher 3.0.1核心特性与集成选型在深入代码之前我们有必要搞清楚SQLCipher 3.0.1这个版本能给我们带来什么以及在不同平台下如何选择集成方式。这决定了后续整个开发流程的顺畅程度。2.1 版本核心特性解析SQLCipher 3.0.1虽然不是一个最新版本但它是一个里程碑式的稳定版奠定了后续许多版本的基础。它的核心加密特性基于成熟的加密库OpenSSL默认或LibTomCrypt。透明的256位AES加密这是其基石。所有数据库页默认1024字节在写入磁盘前会使用CBC模式的AES-256进行加密。加密的粒度是“页”而不是每次写入操作这在安全性和性能之间取得了很好的平衡。密钥则通过PBKDF2基于密码的密钥派生函数2算法派生该过程会引入数万次的哈希迭代极大增加了暴力破解的难度。完整的数据库加密加密的不只是用户数据表。数据库的schema表结构、索引、视图等元数据以及SQLite用于保证事务完整性的回滚日志-journal文件和预写日志-wal文件都会被一并加密。这确保了整个数据库文件体系的机密性。近乎零成本的API兼容性这是SQLCipher最吸引人的地方。对于开发者而言唯一的API变化就是在打开数据库后、执行任何操作前需要调用一次PRAGMA key ‘your-passphrase’;来提供密钥。除此之外所有的sqlite3_*API函数、SQL语法都保持不变。你的业务代码几乎无需改动。良好的性能表现由于加密/解密发生在I/O层且AES算法在现代CPU上通常有硬件加速支持因此引入的性能开销在大多数应用场景下是可接受的。根据官方数据和我的实测在主流移动设备上加密数据库的读写性能相比明文数据库通常有10%-20%的损耗这对于强调安全的应用来说是完全值得的。2.2 各平台集成方案对比与选型集成SQLCipher首要问题是获取编译好的库文件。你有两个主要选择自己编译或使用官方预编译的二进制包。对于绝大多数团队我强烈建议后者除非你有极强的定制化需求比如更换加密后端。Android平台对于Android集成最为方便。你可以直接通过Gradle依赖官方维护的AAR包。在你的模块级build.gradle文件中添加dependencies { implementation ‘net.zetetic:android-database-sqlcipher:4.5.3aar’ // 注意这是较新版本 // 如果你坚持使用3.0.1可能需要寻找历史版本或自行编译 }注意官方Maven仓库提供的版本通常较新。SQLCipher 3.0.1是一个较老的版本在Android上你可能需要寻找历史归档或者使用后续兼容API的版本如4.x。新版本在API上保持了高度兼容但内部性能和安全性有提升。我建议在非强制要求下使用官方推荐的最新稳定版。iOS/macOS平台在苹果生态中最主流的方式是使用CocoaPods或Carthage集成。CocoaPods的Podfile配置如下pod ‘SQLCipher’这条命令会拉取并配置好SQLCipher并将你的项目中的SQLite替换为SQLCipher版本。集成后你需要确保在项目的Other Linker Flags中添加-DSQLITE_HAS_CODEC和-DSQLITE_TEMP_STORE2等预处理宏这些通常在Pod集成后会自动完成。Windows/Linux/跨平台C/C项目对于桌面端或需要原生C接口的项目你需要下载对应平台的预编译二进制文件.dll,.so,.dylib以及头文件。或者从GitHub获取源码进行编译。编译过程需要OpenSSL开发库。一个关键的实操心得是确保你的应用程序在分发时其链接的SQLCipher动态库与编译时使用的版本严格一致否则可能会遇到诡异的运行时错误。选型总结移动端Android/iOS优先使用官方提供的包管理依赖Gradle/CocoaPods省时省力兼容性好。桌面端或嵌入式根据目标平台下载预编译库如果平台特殊或需要深度定制则从源码编译。版本选择除非项目有历史包袱必须使用3.0.1否则建议评估并使用更新的稳定版本如4.x系列以获得更好的安全补丁和性能优化。3. 核心实战从创建到管理的全流程理论说再多不如一行代码。接下来我们进入实战环节。我会以C API和Android环境为例展示核心操作其他平台的思路是相通的。3.1 初始化与数据库加密创建首先你需要引入SQLCipher库。在Android中使用SQLiteOpenHelper的SQLCipher实现版本。import net.sqlcipher.database.SQLiteDatabase; import net.sqlcipher.database.SQLiteOpenHelper; public class MyDatabaseHelper extends SQLiteOpenHelper { private static final String DATABASE_NAME “encrypted.db”; private static final int DATABASE_VERSION 1; public MyDatabaseHelper(Context context) { super(context, DATABASE_NAME, null, DATABASE_VERSION); // 关键一步在Helper实例化后加载SQLCipher本地库 SQLiteDatabase.loadLibs(context); } Override public void onCreate(SQLiteDatabase db) { // 注意此时db已经是可用的加密数据库连接 db.execSQL(“CREATE TABLE secret_data (id INTEGER PRIMARY KEY, info TEXT)”); } Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { // 升级逻辑 } public SQLiteDatabase getWritableDatabase(String passphrase) { // 重写此方法传入密钥 return super.getWritableDatabase(passphrase); } }使用数据库时MyDatabaseHelper helper new MyDatabaseHelper(this); String userPassphrase “MySuperSecretPassphrase123!”; // 密钥应从安全渠道获取切勿硬编码 SQLiteDatabase db helper.getWritableDatabase(userPassphrase); // 现在可以像使用普通SQLite一样操作db了 db.execSQL(“INSERT INTO secret_data (info) VALUES (?)”, new Object[]{“加密存储的数据”});关键解析与避坑指南密钥管理是生命线示例中硬编码密钥是绝对错误的示范。在实际项目中密钥应该通过安全的方式生成和存储。常见做法包括Android使用Android Keystore系统生成一个非对称密钥对用公钥加密一个随机生成的数据库密钥将加密后的结果存储在SharedPreferences中。每次使用时用Keystore中的私钥解密出数据库密钥。iOS使用Keychain服务来安全存储密钥。绝对不要将密钥直接写在代码、资源文件或明文配置中。SQLiteDatabase.loadLibs(context)这行代码至关重要它负责在运行时加载SQLCipher的本地库.so文件。必须在任何数据库操作前调用通常放在Helper的构造函数或Application的onCreate中。密码复杂性密钥密码应有足够的强度建议使用随机生成的高熵值字符串而非用户输入的简单密码。如果依赖用户密码必须引导其设置强密码。3.2 加密数据库的迁移与版本升级这是一个非常实际的场景你的App已经发布现在需要在已有明文数据库的基础上升级到加密数据库。迁移策略明文 - 加密备份明文数据库使用旧的、不链接SQLCipher的代码打开明文数据库将其所有数据读出或直接复制文件备份。创建新的加密数据库使用集成了SQLCipher的新代码用新密钥创建一个新的空数据库。ATTACH与数据转移这是核心技巧。你可以在一个加密数据库的连接中使用SQL的ATTACH DATABASE命令挂载旧的明文数据库文件作为只读然后通过INSERT INTO ... SELECT FROM ...语句将所有表数据复制过来。-- 在加密数据库连接中执行 ATTACH DATABASE ‘plaintext.db’ AS plain KEY ‘’; -- 假设表结构相同 INSERT INTO main.secret_data SELECT * FROM plain.secret_data; DETACH DATABASE plain;删除旧文件替换新文件数据转移完成后安全地删除旧的明文数据库文件并将新的加密数据库文件置于正确位置。版本升级中的加密处理在SQLiteOpenHelper.onUpgrade方法中你获得的SQLiteDatabase参数已经是加密连接。这意味着你可以在升级逻辑中直接执行需要加密环境的SQL语句。但务必注意升级脚本本身如ALTER TABLE也会在加密环境下执行这通常没有问题。关键在于确保升级操作是幂等的并且处理好可能因加密导致的性能下降如果升级涉及大量数据迁移。3.3 日常查询、事务与性能优化日常使用与普通SQLite无异但以下几点需要特别关注1. 连接与密钥缓存每次调用getWritableDatabase(passphrase)时SQLCipher都会使用该密钥尝试解密数据库头。这是一个相对耗时的操作。因此最佳实践是在应用生命周期内保持一个全局的、安全的数据库连接实例避免反复打开关闭。在Android中通常使用单例模式管理你的MyDatabaseHelper和数据库连接。2. 事务的强制使用对于批量写入操作必须使用事务。这一点在加密数据库中比在明文数据库中更重要。因为每次写入都涉及加密计算如果不使用事务每个INSERT/UPDATE都会导致一次独立的磁盘I/O和加密操作性能会急剧下降。db.beginTransaction(); try { for (DataItem item : dataList) { db.insert(“secret_data”, null, item.toContentValues()); } db.setTransactionSuccessful(); } finally { db.endTransaction(); }实测表明将1000条插入操作包裹在一个事务中速度可以提升数十倍。3. 索引与查询优化加密不影响你创建和使用索引。但是因为数据在磁盘上是加密的所以“覆盖索引”的优势可能会被削弱因为数据库引擎仍然需要解密索引指向的数据页来获取非索引列。优化原则不变分析慢查询为WHERE、JOIN、ORDER BY子句中的列建立索引。使用EXPLAIN QUERY PLAN来查看SQLite的执行计划。4. 内存与页面大小调整SQLCipher支持标准的SQLite性能调优PRAGMA。你可以根据数据量调整page_size和cache_size。例如如果存储大量文本或BLOB增大page_size如4096可能有益。增大cache_size可以让更多解密后的页面缓存在内存中减少重复解密。PRAGMA page_size 4096; PRAGMA cache_size -2000; -- 表示约2000页的缓存这些设置最好在数据库创建后、建表前执行。4. 高级议题与安全加固当你熟练了基本操作后下面这些高级话题能帮助你构建更健壮的安全体系。4.1 密钥的生命周期管理与轮换静态的、永不更换的密钥存在风险。理想情况下应支持密钥轮换。密钥轮换方案导出再导入法类似于明文到加密的迁移。使用旧密钥打开数据库将其所有数据导出例如通过.dump命令生成SQL脚本或编程式读取所有数据。然后用新密钥创建一个新数据库再将数据导入。此方法适用于数据量不大或可以接受停机时间的场景。SQLCipher的rekeyPRAGMASQLCipher提供了一个便捷的PRAGMA rekey命令可以在数据库打开后直接更改其加密密钥。PRAGMA key ‘old-passphrase’; -- ... 执行一些操作确保密钥正确 ... PRAGMA rekey ‘new-passphrase’;重要警告rekey操作会重写整个数据库文件这是一个阻塞性的I/O密集型操作对于大型数据库可能会耗时很长必须在后台线程进行并妥善处理中断和错误做好回滚准备。4.2 抵御常见攻击的配置策略除了加密额外的配置可以提升防御等级。PRAGMA cipher_hmac_algorithm与PRAGMA kdf_iterkdf_iter密钥派生迭代次数默认是64000。你可以增加这个值例如到256000这会使密钥派生过程更慢从而极大增加暴力破解的难度。但这也会轻微影响每次打开数据库的速度。需要在安全性和用户体验间权衡。cipher_hmac_algorithm用于设置HMAC算法确保数据完整性。默认是SHA512通常无需修改。-- 在提供KEY之后执行其他操作之前设置 PRAGMA key ‘passphrase’; PRAGMA kdf_iter 256000; PRAGMA cipher_hmac_algorithm HMAC_SHA512;关闭内存统计减少信息泄露PRAGMA secure_delete ON; -- 安全删除覆盖已删除数据 PRAGMA auto_vacuum FULL; -- 结合secure_delete更好地清理空间PRAGMA secure_delete ON会确保被删除的数据在磁盘上被覆盖防止通过磁盘恢复工具提取残迹。4.3 与上层ORM框架如Room的协作在现代Android开发中Room Persistence Library是官方推荐的SQLite抽象层。让Room与SQLCipher协同工作你需要提供一个由SQLCipher支持的SupportSQLiteOpenHelper.Factory。添加依赖需要同时引入Room和SQLCipher for Android的Room扩展库。dependencies { def room_version “2.5.0” implementation “androidx.room:room-runtime:$room_version” kapt “androidx.room:room-compiler:$room_version” implementation “androidx.room:room-ktx:$room_version” // 可选用于协程支持 implementation ‘net.zetetic:android-database-sqlcipher:4.5.3’ // SQLCipher implementation ‘com.commonsware.cwac:saferoom.x:1.3.1’ // 或类似的适配库 }saferoom这类库封装了SQLCipher并提供了与Room兼容的Factory。配置Room DatabaseDatabase(entities [SecretData::class], version 1) abstract class AppDatabase : RoomDatabase() { abstract fun secretDao(): SecretDao companion object { Volatile private var INSTANCE: AppDatabase? null fun getInstance(context: Context, passphrase: ByteArray): AppDatabase { return INSTANCE ?: synchronized(this) { val factory SafeHelperFactory(passphrase) // 来自saferoom库 val instance Room.databaseBuilder( context.applicationContext, AppDatabase::class.java, “encrypted_room.db” ) .openHelperFactory(factory) // 关键注入SQLCipher工厂 .build() INSTANCE instance instance } } } }这样Room生成的所有SQL操作都会通过SQLCipher加密。5. 调试、问题排查与性能监控即使一切配置正确在开发中你仍可能遇到问题。这里记录一些典型场景和排查思路。5.1 常见错误与解决方案速查表错误现象可能原因排查步骤与解决方案file is encrypted or is not a database1. 密钥错误。2. 数据库文件根本不是SQLite/SQLCipher格式。3. 使用了不兼容的SQLCipher版本。1. 确认密钥与创建时一致检查密钥管理逻辑。2. 用file命令或十六进制查看器检查文件头。SQLCipher文件头是SQLite format 3\000。3. 确保生成和使用数据库的库版本一致。not an error但数据库打开后查询为空密钥正确但提供的密码派生参数kdf_iter, cipher等与创建时不一致。在创建和打开数据库时使用完全相同的PRAGMA设置序列。建议将kdf_iter、cipher_hmac_algorithm等设置封装为一个方法确保一致。性能极差尤其是写入1. 未使用事务进行批量操作。2.page_size设置不合理。3. 磁盘I/O瓶颈。1.务必将批量写入包裹在事务中。2. 根据存储内容调整page_size通常4096是好的起点。3. 检查是否在UI线程执行大量操作移至后台线程。使用Profiler工具监控。Android上UnsatisfiedLinkErrorSQLCipher本地库未正确加载。1. 确认SQLiteDatabase.loadLibs(context)在数据库操作前被调用。2. 检查APK的lib目录下是否包含对应ABI的.so文件。3. 对于x86模拟器确保依赖了x86版本的库。数据库升级onUpgrade失败升级脚本在加密环境下有语法错误或逻辑错误。1. 先在一个独立的加密数据库测试环境中验证升级脚本。2. 确保升级操作是幂等的可重复执行。3. 在升级过程中也使用事务。5.2 性能监控与调优实践使用SQLite TraceSQLCipher支持标准的SQLite性能分析工具。你可以注册一个SQLiteTrace对象来监听查询执行时间。// Android SQLCipher 示例 SQLiteDatabase db ...; db.setTraceCallback(new SQLiteTrace.Callback() { Override public void onTrace(String sql, long timeMs) { if (timeMs 100) { // 记录耗时超过100ms的查询 Log.w(“SQL_PERF”, “Slow query: “ sql “ took “ timeMs “ms”); } } });解释查询计划对于复杂查询使用EXPLAIN QUERY PLAN前缀来分析。关注是否使用了预期的索引是否有全表扫描。EXPLAIN QUERY PLAN SELECT * FROM secret_data WHERE info LIKE ‘%keyword%’;基准测试在应用开发早期建立加密数据库与明文数据库的性能基准。针对典型操作如插入1000条记录、复杂联表查询进行对比测试量化加密带来的性能影响做到心中有数。5.3 数据备份与恢复的特别考量加密数据库的备份不能简单地复制.db文件因为密钥也需要安全地备份。一个完整的备份方案应包括数据库文件本身。用于解密该数据库的密钥必须以加密形式存储例如用主用户密码或设备硬件密钥二次加密。创建数据库时使用的所有PRAGMA配置如kdf_iter这些是解密过程的必要参数。在恢复时必须使用完全相同的密钥和PRAGMA配置来打开备份的数据库文件。因此在设计备份系统时务必将这些元信息与数据库文件一同安全地打包和存储。

相关新闻

GetQzonehistory:一键备份QQ空间说说,找回你的青春记忆!

GetQzonehistory:一键备份QQ空间说说,找回你的青春记忆!

GetQzonehistory:一键备份QQ空间说说,找回你的青春记忆! 【免费下载链接】GetQzonehistory 获取QQ空间发布的历史说说 项目地址: https://gitcode.com/GitHub_Trending/ge/GetQzonehistory 还记得那些年你在QQ空间留下的青春足迹吗&am…

2026/10/13 0:17:30 阅读更多 →
2026年PaperPass AIGC检测达标指南:PaperPass AI率超标4.8元快速达标完整处理方案

2026年PaperPass AIGC检测达标指南:PaperPass AI率超标4.8元快速达标完整处理方案

2026年PaperPass AIGC检测达标指南:PaperPass AI率超标4.8元快速达标完整处理方案 针对PaperPass AIGC检测达标专门整理了一套方案——平台有差异,策略也要对应调整。 核心工具:嘎嘎降AI(www.aigcleaner.com)&#x…

2026/10/9 11:28:08 阅读更多 →
蓝速 AI 双屏翻译机:型材机身与高性价比实测避坑指南

蓝速 AI 双屏翻译机:型材机身与高性价比实测避坑指南

在涉外商务接待或跨国团队协作的场景中,沟通效率往往直接决定了合作的成败。很多从业者都遇到过这样的尴尬时刻:双方语言不通,只能依赖手机里的翻译 APP,或者手持一个廉价的塑料翻译棒,在两人之间来回传递。这种“接力…

2026/10/1 12:10:33 阅读更多 →

最新新闻

在河北开发直播 APP,怎么挑选靠谱的软件公司?

在河北开发直播 APP,怎么挑选靠谱的软件公司?

河北不少创业者、企业都想搭建自己的直播 APP,带货直播、付费课程、娱乐打赏、私域直播等需求越来越多。但直播属于音视频高并发项目,技术门槛远高于普通商城和管理系统。很多本地软件公司只会做简单小程序,并不具备流媒体开发经验&#xff0…

2026/10/15 0:47:40 阅读更多 →
Python requests实现人人网自动登录:Cookie、验证码与会话管理全攻略

Python requests实现人人网自动登录:Cookie、验证码与会话管理全攻略

简介:这份人人网(校内)自动登录的Java实现,面向需要模拟登录校内平台的开发者、测试人员或学生。由于网上流传的登录代码多针对旧版校内接口,往往无法直接套用,作者梳理了当前人人网登录流程并编写出简易可…

2026/10/15 0:47:40 阅读更多 →
软件开发想要少踩坑,产品经理才是项目的 “翻译官” 和总设计师

软件开发想要少踩坑,产品经理才是项目的 “翻译官” 和总设计师

很多人做软件定制,关注点只放在程序员、代码、服务器上,觉得只要有开发就能把项目做出来,常常忽略产品经理这个角色。等到项目推进一半,才发现功能逻辑混乱、需求来回改动、做出来的产品和自己预想完全不符,返工不断、…

2026/10/15 0:47:40 阅读更多 →
QML与C++交互:上下文属性、类型注册与单例详解

QML与C++交互:上下文属性、类型注册与单例详解

1. 先想清楚一个问题:QML和C为什么要互相打交道接触Qt QML开发的人应该都有这种感觉:QML写界面确实快,声明式语法、属性绑定、动画、状态切换,一套组合拳下来,界面代码量比传统Widget写法少一大截。但界面做得再漂亮&a…

2026/10/15 0:47:40 阅读更多 →
SpringBoot文件上传临时目录失效异常解析与解决方案

SpringBoot文件上传临时目录失效异常解析与解决方案

1. 问题背景与核心需求拆解文件上传这个功能,几乎每个后端项目都会碰到。不管是用户头像、Excel批量导入、还是附件管理,只要涉及文件从客户端传到服务端,就绕不开multipart/form-data这套机制。SpringBoot 默认集成了 StandardServletMultip…

2026/10/15 0:47:40 阅读更多 →
区间DP解“拿糖果”:从贪心误区到最优策略实战解析

区间DP解“拿糖果”:从贪心误区到最优策略实战解析

说实话,我第一次看到“拿糖果”这道题的时候,差点把它当成热身题给秒了。题面本身非常朴素:有 n 堆糖果排成一行,每堆糖果数量用一个整数数组表示,两个人轮流从最左端或最右端拿走一整堆,直到全部取完&…

2026/10/15 0:46:40 阅读更多 →

日新闻

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

Docker Compose 容器化部署 ChirpStack LoRaWAN 网络服务器实战

1. 为什么选择容器化方式部署 LoRa 网络服务LoRa 物联网项目落地时,网络服务器是整个链路的核心枢纽。它负责接收网关上报的数据包、完成去重与解密、再把有效载荷分发给上层应用。早期大家习惯把网络服务器直接装在物理机上,依赖一堆系统库和特定版本的…

2026/10/15 0:00:46 阅读更多 →
共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

共享LLM服务下的跨模型自动扩缩容:Kubernetes实战与避坑指南

1. 共享推理服务里,扩缩容到底难在哪做过大模型推理服务部署的人,大概都经历过这样的场景:一个团队共用一套推理集群,A 业务跑的是 7B 的小模型,B 业务跑的是 72B 的大模型,C 业务白天流量高、晚上几乎归零…

2026/10/15 0:00:46 阅读更多 →
Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

Systemd 启动阶段根文件系统只读之谜:fstab 与 remount-fs 服务深度解析

1. 引子:一次内核恐慌引发的追查先从一个真实场景说起。某次我给一台老旧的嵌入式设备折腾系统裁减,为了把启动时间压进两秒以内,我手贱地把一串自认为“没用”的 systemd 服务给 disable 了,其中就包括systemd-remount-fs.servic…

2026/10/15 0:00:46 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/14 3:30:28 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/14 16:30:29 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/14 3:29:58 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 22:45:47 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/14 7:53:34 阅读更多 →