# 番茄小说 API Go 语言实现的番茄小说非官方 API 服务,完整实现了签名算法、设备注册、密钥管理等核心功能。 ## 功能特性 ### 核心功能 - **书籍搜索** - 关键词搜索,支持分页 - **书籍详情** - 获取书籍基本信息、封面、作者等 - **章节目录** - 获取完整章节列表 - **章节内容** - 获取正文内容,支持纯文本/HTML模式 - **批量接口** - 支持批量获取书籍详情和章节内容 ### 内容类型 - 📖 小说/电子书 - 🎨 漫画 - 🎵 音频/有声书 - 🎬 视频 ### 评论功能 - 章节段评(段落评论) - 书籍书评 - 评论 HTML 渲染 ### 分类体系 - 分类首页数据 - 分类详情页(支持筛选、排序、分页) ### 技术特性 - **签名算法** - Gorgon、8404、Argus、Ladon、Khronos - **设备密钥池** - 多设备轮换、自动补充 - **多级缓存** - 正文/详情/目录等 24 小时缓存,搜索/分类短缓存;存储后端可选 SQLite / PostgreSQL / Redis - **配置热更新** - 修改配置无需重启 - **访问控制** - AccessKey 验证(常量时间比较防时序攻击),可扩展保护全部业务接口 - **优雅退出** - 超时保护、信号驱动的平滑关闭 - **错误规范** - 统一 JSON 错误响应,缺参 400 / 服务端错误 500 ## 项目结构 ```tree fanqie-go/ ├── cmd/fanqie/ # 程序入口 │ └── main.go # 主函数,初始化服务 ├── config/ # 配置文件 │ └── config.yaml # 配置文件 ├── emoji/ # 表情图片静态资源 ├── internal/ │ ├── algos/ # 签名算法实现 │ │ ├── gorgon.go # Gorgon 签名算法 │ │ ├── algo8404.go # 8404 签名算法 │ │ ├── argus.go # Argus 签名算法 │ │ ├── ladon.go # Ladon 签名算法 │ │ ├── signer.go # 签名管理器 │ │ ├── switcher.go # 算法切换器 │ │ ├── sm3.go # SM3 哈希算法 │ │ ├── simon.go # Simon 对称加密 │ │ ├── pkcs7.go # PKCS7 填充 │ │ ├── protobuf.go # Protobuf 协议 │ │ └── bytebuf.go # 字节缓冲区 │ ├── common/ # 公共工具 │ │ ├── logger.go # 日志工具 │ │ ├── http.go # HTTP 工具 │ │ └── utils.go # 通用工具 │ ├── config/ # 配置管理 │ │ ├── config.go # 配置加载 │ │ └── watcher.go # 配置热更新 │ ├── fqapi/ # API 封装层 │ │ ├── cache_manager.go # SQLite 缓存管理 │ │ ├── device_key_pool.go # 设备密钥池 │ │ ├── device_register.go # 设备注册 │ │ ├── register_key.go # 密钥注册 │ │ ├── dhcry.go # DH 加密交换 │ │ ├── ttencrypt.go # TTEncrypt 加密 │ │ ├── search.go # 搜索接口 │ │ ├── detail.go # 书籍详情 │ │ ├── catalog.go # 章节目录 │ │ ├── content.go # 章节内容 │ │ ├── multi_content.go # 批量内容 │ │ ├── multi_detail.go # 批量详情 │ │ ├── item_summary.go # 章节摘要 │ │ ├── category_front.go # 分类首页 │ │ ├── category_landing.go # 分类详情 │ │ ├── audio.go # 音频 │ │ ├── video.go # 视频 │ │ ├── manga.go # 漫画 │ │ ├── manga_proxy.go # 漫画代理 │ │ ├── review.go # 评论 │ │ ├── content_parser.go # 内容解析 │ │ ├── content_utils.go # 内容工具 │ │ ├── emoji.go # 表情管理 │ │ ├── device_config.go # 设备配置 │ │ └── gorgon_utils.go # Gorgon 请求封装 │ └── handlers/ # HTTP 处理器 │ ├── common.go # 通用处理 │ ├── book.go # 书籍接口 │ ├── content.go # 内容接口 │ ├── media.go # 媒体接口 │ ├── review.go # 评论接口 │ ├── category.go # 分类接口 │ ├── manga_proxy.go # 漫画代理 │ └── status.go # 状态页面 └── go.mod # Go 模块定义 ``` ## 快速开始 ### 环境要求 - Go 1.24+ - SQLite3 ### 安装运行 ```bash # 克隆项目 git clone https://github.com/cyqddx/fanqie-go.git cd fanqie-go # 运行服务 go run ./cmd/fanqie ``` 服务默认启动在 `http://0.0.0.0:40180` ## API 接口文档 机器可读的完整接口定义见 [openapi.yaml](openapi.yaml)(OpenAPI 3.1,可直接导入 Swagger UI / Apifox / Postman)。 ### 基础接口 | 接口 | 方法 | 说明 | | ------ | ------ | ------ | | `GET /` | GET | 服务首页 | | `GET /healthz` | GET | 存活探针(不校验密钥,供容器/反代使用) | | `GET /status` | GET | 服务状态(需 AccessKey) | | `GET /self-info` | GET | 自我信息(需 AccessKey) | | `POST /vacuum` | POST | 数据库压缩(需 AccessKey) | ### 书籍相关 | 接口 | 方法 | 说明 | 参数 | | ------ | ------ | ------ | ------ | | `/search` | GET | 搜索书籍 | `query`(或 `key`), `tab_type`, `offset` | | `/detail` | GET | 书籍详情 | `book_id` | | `/info` | GET | 书籍详情(同 detail) | `book_id` | | `/catalog` | GET | 章节目录 | `book_id` | | `/directory/all_items` | GET | 章节目录(同 catalog) | `book_id` | | `/multi-detail` | GET | 批量书籍详情 | `book_id`(逗号分隔) | ### 内容相关 | 接口 | 方法 | 说明 | 参数 | | ------ | ------ | ------ | ------ | | `/content` | GET | 章节内容 | `item_id` | | `/multi-content` | GET | 批量章节内容 | `book_id`, `item_ids`(逗号分隔) | | `/item-summary` | GET | 章节摘要 | `book_id`, `item_ids`(逗号分隔) | ### 评论相关 | 接口 | 方法 | 说明 | 参数 | | ------ | ------ | ------ | ------ | | `/chapter_review` | GET | 章节评论 | `book_id`, `item_id` | | `/review` | GET | 书评列表 | `book_id`, `item_id`, `para`, `comment_id`, `offset`, `limit` | | `/review_html` | GET | 评论 HTML | `book_id`, `item_id`, `para` | ### 分类相关 | 接口 | 方法 | 说明 | 参数 | | ------ | ------ | ------ | ------ | | `/category-front` | GET | 分类首页 | - | | `/category-landing` | GET | 分类详情 | `category_id`, `word_number`, `book_status`, `sort_by`, `offset` | ### 媒体相关 | 接口 | 方法 | 说明 | 参数 | | ------ | ------ | ------ | ------ | | `/audio` | GET | 音频内容 | `item_ids`, `tone_id`, `output` | | `/video` | GET | 视频内容 | `item_ids` | | `/manga` | GET | 漫画内容 | `item_ids`(或 `item_id`), `show_html`, `output` | | `/manga/image/{itemID}/{index}` | GET | 漫画图片 | 路径参数 | ## 内容获取示例 ### 搜索书籍 ```bash GET http://localhost:40180/search?keyword=斗罗大陆 ``` ### 获取书籍详情 ```bash GET http://localhost:40180/detail?book_id=xxx ``` ### 获取章节目录 ```bash GET http://localhost:40180/catalog?book_id=xxx ``` ### 获取章节内容 ```bash GET http://localhost:40180/content?book_id=xxx&chapter_id=xxx ``` 支持以下 URL 参数覆盖默认配置: | 参数 | 说明 | 可选值 | | ------ | ------ | ------ | | `text_mode` | 文本模式 | `plain`(纯文本), `html`(HTML) | | `img_mode` | 图片模式 | `remove`(移除), `keep`(保留) | | `review_mode` | 评论模式 | `remove`(移除), `keep`(保留) | ### 批量获取 ```bash GET http://localhost:40180/multi-detail?book_ids=id1,id2,id3 GET http://localhost:40180/multi-content?chapter_ids=id1,id2,id3 ``` ## 配置说明 ### 完整配置项 配置文件位于 `config/config.yaml`: ```yaml # 服务器配置 server: host: "0.0.0.0" # 监听地址 port: "40180" # 监听端口 access_key: "" # 访问密钥(可选) protect_all: false # 业务接口也要求访问密钥(公网部署建议开启) # 番茄小说配置 fanqie: # 签名算法: "gorgon" / "8404" algorithm: "gorgon" # 签名方法: # - "sign2": X-Gorgon + X-Khronos # - "sign4": X-Gorgon + X-Ladon + X-Argus + X-Khronos signature: "sign4" # 内容处理 content: remove_images: false # 移除图片 remove_image_desc: true # 移除图片描述 remove_blank_lines: true # 移除空行 remove_html_tags: true # 移除 HTML 标签 remove_chapter_title: true # 移除章节标题 add_paragraph_indent: false # 添加段落缩进 double_newline: false # 段落间双换行 enable_review: true # 启用段评 # 漫画处理 manga: # 输出模式: # - "proxy": 代理模式 # - "url": 直接返回图片 URL # - "data_uri": Base64 编码 output_mode: "url" # 缓存配置 cache: enabled: true # 启用缓存 backend: sqlite # 存储后端: sqlite | postgres sqlite_path: "./cache.db" # SQLite 路径(backend 为 sqlite 时使用) # PostgreSQL连接配置(backend 为 postgres 时使用) postgres: host: "127.0.0.1" # 主机 port: 5432 # 端口 user: "postgres" # 用户名 password: "" # 密码 database: "fanqie" # 数据库名 sslmode: "disable" # SSL 模式: disable | prefer | require redis: # Redis 缓存(正文缓存与音频代理缓存,统计数据/设备池仍在 SQL 库) enabled: false host: "127.0.0.1" # 主机 port: 6379 # 端口 password: "" # 密码 db: 0 # 数据库编号 cleanup_enabled: true # 启用自动清理 cleanup_seconds: 86400 # 清理间隔(秒) # 设备密钥池 device_key_pool: enabled: true # 启用设备池 initial_size: 20 # 初始设备数 min_size: 10 # 最小设备数 max_size: 30 # 最大设备数 ``` ### 敏感配置(.env) 密码等敏感值不建议写进 `config.yaml`(会进 git 历史)。复制 `.env.example` 为 `.env` 填入真实值即可,`.env` 已被 gitignore: ```bash cp .env.example .env ``` 支持的环境变量(优先于 `config.yaml` 对应项): | 环境变量 | 覆盖配置 | 说明 | | -------- | -------- | ---- | | `FQ_SERVER_ACCESS_KEY` | `server.access_key` | 服务访问密钥 | | `FQ_PG_HOST` | `cache.postgres.host` | PostgreSQL 主机 | | `FQ_PG_USER` | `cache.postgres.user` | PostgreSQL 用户名 | | `FQ_PG_PASSWORD` | `cache.postgres.password` | PostgreSQL 密码 | | `FQ_PG_DATABASE` | `cache.postgres.database` | PostgreSQL 数据库名 | | `FQ_REDIS_HOST` | `cache.redis.host` | Redis 主机 | | `FQ_REDIS_PASSWORD` | `cache.redis.password` | Redis 密码 | 已有环境变量优先于 `.env` 文件中的值。 ### 配置说明表 | 配置项 | 说明 | 默认值 | | ------ | ------ | ------ | | `server.host` | HTTP 服务监听地址 | `0.0.0.0` | | `server.port` | HTTP 服务监听端口 | `40180` | | `server.access_key` | 访问密钥,设为空则不验证 | - | | `server.protect_all` | 业务接口是否也要求访问密钥 | `false` | | `fanqie.algorithm` | 签名算法 `gorgon` / `8404` | `gorgon` | | `fanqie.signature` | 签名方法 `sign2` / `sign4` | `sign4` | | `fanqie.content.*` | 正文内容处理选项 | 见上文 | | `fanqie.manga.output_mode` | 漫画输出模式 | `url` | | `cache.enabled` | 是否启用正文内容缓存 | `true` | | `cache.backend` | SQL 存储后端 `sqlite` / `postgres` | `sqlite` | | `cache.sqlite_path` | SQLite 数据库路径 | `./cache.db` | | `cache.postgres.host` | PostgreSQL 主机 | `127.0.0.1` | | `cache.postgres.port` | PostgreSQL 端口 | `5432` | | `cache.postgres.user` | PostgreSQL 用户名 | `postgres` | | `cache.postgres.password` | PostgreSQL 密码 | 空 | | `cache.postgres.database` | PostgreSQL 数据库名 | `fanqie` | | `cache.postgres.sslmode` | SSL 模式 | `disable` | | `cache.redis.enabled` | 启用 Redis 缓存(正文与音频代理缓存走 Redis) | `false` | | `cache.redis.host` | Redis 主机 | `127.0.0.1` | | `cache.redis.port` | Redis 端口 | `6379` | | `cache.redis.password` | Redis 密码 | 空 | | `cache.redis.db` | Redis 数据库编号 | `0` | | `device_key_pool.enabled` | 是否启用设备密钥池 | `true` | | `device_key_pool.initial_size` | 初始设备数量 | `20` | | `device_key_pool.min_size` | 最小设备数量 | `10` | | `device_key_pool.max_size` | 最大设备数量 | `30` | ## 签名算法详解 ### 算法实现 项目实现了番茄小说的核心签名算法: | 算法 | 文件 | 说明 | | ------ | ------ | ------ | | **Gorgon** | `algos/gorgon.go` | 核心签名算法,生成 X-Gorgon、X-Khronos、X-SS-REQ-Ticket | | **8404** | `algos/algo8404.go` | 另一种签名算法实现 | | **Argus** | `algos/argus.go` | 增强签名,包含 ProtoBuf、SM3、Simon、AES 加密 | | **Ladon** | `algos/ladon.go` | 附加签名,基于 MD5 变换 | | **Khronos** | 内嵌于 Gorgon | 时间戳签名 | ### 签名方法 - **sign2**: X-Gorgon + X-Khronos(基础签名) - **sign4**: X-Gorgon + X-Ladon + X-Argus + X-Khronos(完整签名) ## 设备密钥池 项目实现了设备密钥池管理: - **自动注册** - 启动时自动注册多个设备 - **密钥轮换** - 请求时自动切换设备 - **自动补充** - 设备数量低于阈值时自动注册新设备 - **持久化存储** - 设备信息保存到 SQLite ## 缓存机制 - **接口缓存** - 命中直接返回,不打上游(Redis 启用时优先走 Redis) - **自动清理** - 定期清理过期缓存(Redis 由 TTL 自动过期) - **数据库压缩** - 支持 VACUUM 操作优化数据库 | 接口 | 缓存时长 | | ------ | ------ | | `/content` | 24 小时 | | `/detail`、`/info`、`/catalog`、`/multi-detail`、`/item-summary` | 24 小时 | | `/search`、`/category-front`、`/category-landing` | 10 分钟 | | `/audio` 代理链接 | 2 小时(匹配 CDN 有效期) | 失败响应不缓存;评论类接口为动态数据,不缓存。 ## 技术栈 - **Go 1.24** - 编程语言 - **net/http** - 标准库 HTTP 服务(超时保护 + 优雅退出) - **SQLite3 / PostgreSQL / Redis** - 缓存与存储 - **Viper** - 配置管理 - **goquery** - HTML 解析 ## 注意事项 - 本项目仅供学习和研究使用 - 请遵守番茄小说的服务条款 - 请合理使用,避免对官方服务造成影响 - 签名算法和设备注册可能随时失效 ## License MIT License