单本小说独立应用
详情介绍
SingleNovel 单本小说采集使用说明
功能概述
SingleNovel 插件(目录:plugins/SingleNovel)内置 3 个笔趣阁系目标站的默认采集规则,支持:
- 后台一键配置:选目标站 + 填书籍 URL 路径,保存即可
- 宝塔计划任务自动同步:访问
/novel/cron?token=xxx增量拉取新章节 - 反爬绕过:52wx.com 的 JS cookie 挑战自动处理
- 纯净落库:章节标题从
<title>/ 最后一个<h1>准确提取,正文清洗广告 - 防重复:
(sourcesite, sourceurl)唯一键保证幂等
目录结构
plugins/SingleNovel/
├── SingleNovelPlugin.php ← 插件入口 + 配置 schema + 安装逻辑
├── install.sql ← snv_chapter / snv_volume 表结构
├── routes.php ← 前台 /novel/* + 后台 /admin/snv/* + cron
├── service/
│ └── NovelCrawlService.php ← 采集核心(HTTP + 解析 + 增量同步)
├── controller/
│ ├── Index.php ← 前台小说首页 / 目录 / 阅读页
│ ├── Cron.php ← 宝塔计划任务入口 /novel/cron
│ └── admin/
│ ├── Chapter.php ← 后台章节管理
│ ├── Volume.php ← 后台分卷管理
│ └── Crawl.php ← 后台采集管理(立即同步 / 重置令牌)
└── view/
└── admin/
└── crawl_index.html ← 后台采集设置页(含宝塔接入说明)一、后台配置
步骤 1:安装插件
如果还没装:后台 → 插件管理 → 找到「单本小说」→ 安装(或首次请求时自动触发 ensureSchema())。
步骤 2:填写采集参数
后台 → 插件管理 → 单本小说 → 配置,或直接访问 /admin/snv/crawl:
| 字段 | 示例 | 说明 |
|---|---|---|
| 启用采集同步 | 开启 | 必须打开才能让 cron 生效 |
| 采集目标站 | 52wx | 三选一:52wx.com / biquh.com / biquga.com |
| 书籍 URL 路径 | 0_428 | 从浏览器地址栏复制 https://www.52wx.com/0428/ 的 0428 部分 |
| 落库到分卷 | 0 | 0 表示未分卷;有分卷时选对应分卷可让章节归类 |
| 采集令牌 | 8B0B7B60E35D08EA | 系统自动生成,点击「重置令牌」按钮刷新 |
| 自动更新书名/作者 | 开启 | 可选 |
步骤 3:立即同步一次验证
配置保存后,点击 立即采集 按钮(或直接在浏览器访问 cron URL)。
成功返回示例:
{"code":0,"msg":"ok","data":{"created":20,"updated":0,"skipped":0,"failed":0,"total":2985,"message":"共 2985 章;本次新增 20 章,跳过 0 章,失败 0 章"}}每次请求最多拉取 20 章(防 Nginx 超时、防触发反爬)。宝塔 30 分钟一次即可覆盖全量。
二、宝塔计划任务接入
方式一 · URL 访问(推荐)
- 打开宝塔面板 → 计划任务 → 新增任务
- 任务类型:URL 请求
- URL:
```
http://admin.zz/novel/cron?token=你的采集令牌
```
- 执行周期:每 30 分钟 或 每小时
方式二 · Shell 脚本
curl -s "http://admin.zz/novel/cron?token=你的采集令牌"返回值说明
code | 含义 |
|---|---|
0 | 成功,data.created = 本次新增章数 |
401 | 令牌无效 / 未配置令牌 |
400 | 采集未启用(后台没开 crawlenabled 或没填 bookid) |
500 | 服务端异常,msg 会带错误信息 |
建议配置
- 采集 52wx.com 的 伏天氏(约 2985 章):宝塔 30 分钟一次,首次全量约需 75 次(37 小时),之后每次 1~2 章
- 如果只想同步新章节:建议每日执行 2~3 次即可
三、目标站规则详情
三个内置规则统一放在 NovelCrawlService::SITE_PRESETS:
'52wx' => [
'base_url' => 'https://www.52wx.com',
'charset' => 'GBK', // 注意:编码不是 UTF-8
'book_url_pattern' => '{base}/{book}/',
'user_agent' => 'Mozilla/5.0 ... Chrome/130.0',
...
],| 标识 | 目标站 | 编码 | 反爬 | 实测 |
|---|---|---|---|---|
52wx | www.52wx.com | GBK | 两阶段 cookie jar 绕过 | ✅ 可用 |
biquh | www.biquh.com | UTF-8 | Cloudflare 保护 | 需实际连通测试 |
biquga | www.biquga.com | UTF-8 | 偶发超时 | 需实际连通测试 |
如何新增其它笔趣阁系站点
打开 plugins/SingleNovel/service/NovelCrawlService.php,在 SITE_PRESETS 数组里加一项:
'mybiquge' => [
'base_url' => 'https://www.mybiquge.com',
'charset' => 'UTF-8', // 或 GBK
'book_url_pattern' => '{base}/{book}/',
'chapter_url_pattern' => '{base}/{book}/{chapter_id}.html',
'user_agent' => 'Mozilla/5.0 ...',
'extra_headers' => [
'Referer' => 'https://www.mybiquge.com/',
],
],然后在后台配置的目标站下拉里把 mybiquge 加进去,或直接改 SingleNovelPlugin.php 的 configSchema() extra 数组即可。
四、技术实现要点
1. HTTP 两阶段抓取(绕过 52wx.com 的 JS cookie 挑战)
// 阶段一:触发服务器下发 cookie(52wx 会先返回 403 + 重定向 JS)
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, false);
curl_setopt($ch, CURLOPT_COOKIEJAR, $cookieJar);
curl_exec($ch);
// 阶段二:带 cookie 再抓一次
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
curl_setopt($ch, CURLOPT_COOKIEFILE, $cookieJar);
$body = curl_exec($ch);2. 纯正则 HTML 解析(不依赖 DOMDocument)
笔趣阁系页面的 HTML 极度不规范,DOMDocument::loadHTML 在 GBK 脏页面上返回 0 个节点,故改用纯正则:
- 章节链接:
<a href="...">标题</a>→ 支持三种格式
- 相对路径:18901776.html
- 绝对根路径:/0_428/18901776.html
- 完整 URL:https://www.52wx.com/0_428/18901776.html
- 章节正文:
<div id="content">...</div>(笔趣阁统一容器)
3. 标题智能提取
笔趣阁章节页通常有两个 <h1>:第一个是站点名(如「笔趣阁」),第二个才是真正章节标题。
策略:优先从 <title> 标签去掉 _笔趣阁 等后缀,否则取最后一个非站点名的 h1。
4. 增量同步
- 每次采集前查
snvchapter 表里 sourcesite + source_url已有的记录 - 只对新章节发起 HTTP 请求,跳过已存在的
- 单请求最多 20 章 → 宝塔计划任务多次执行即可全量
5. 幂等防重
表 zsenssnvchapter 有 (sourcesite, sourceurl(200)) 组合唯一键,syncBook() 在批量插入时 catch 唯一键冲突并计为 skipped。
五、表结构速查
CREATE TABLE snv_chapter (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
volume_id INT UNSIGNED DEFAULT 0, -- 所属分卷
title VARCHAR(200), -- 章节标题
subtitle VARCHAR(200),
content MEDIUMTEXT, -- 正文(已清洗)
source_url VARCHAR(500), -- 采集来源 URL
source_site VARCHAR(30), -- 52wx / biquh / biquga
word_count INT UNSIGNED DEFAULT 0,
sort INT,
status TINYINT DEFAULT 1,
view_count INT UNSIGNED DEFAULT 0,
...
KEY idx_source (source_site, source_url(200))
);
CREATE TABLE snv_volume (
id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(120), -- 分卷名
...
);六、常见问题
Q1:采集返回「无法访问书籍页」?
A:目标站可能返回 403/520/超时。检查两点:
- 服务器是否能访问目标站:在服务器上
curl -I https://www.52wx.com/0_428/ - 如果是 403 但命令行 curl 带浏览器 UA 能访问 → 确认代码里
fetchPage()已加了CURLOPT_COOKIEJAR两阶段
Q2:采集成功但标题全是「笔趣阁」?
A:这是旧版本的 cleanTitle() 只取第一个 h1。已在新版本修复为取 <title> 去掉后缀或最后一个非站点名的 h1。
Q3:想换一本书采集?
A:后台插件配置 → 改 crawlbookid → 保存。旧章节保留在 snv_chapter 里不动。
Q4:令牌泄露了?
A:后台 /admin/snv/crawl 页面点击 重置令牌,新 token 会覆盖旧的,宝塔 cron URL 需要同步更新。
Q5:采集完怎么在前台展示?
A:访问 /novel(小说首页)、/novel/catalog(目录)、/novel/chapter?id=xxx(阅读页)。可以在插件配置里开启 takeover_home=1 让根路径直接是小说首页。
七、安全与合规
- 令牌鉴权:cron 接口无登录态,靠
?token=xxx鉴权,token 存插件表configJSON 里,hash_equals()比对 - 速率限制:单请求 20 章 + 200ms 礼貌间隔,避免被封 IP
- 仅抓公开内容:所有解析都针对公开页面,未登录墙、VIP 章节按源站行为跳过
请遵守目标站 robots.txt 和相关法律法规
文档版本:与 SingleNovel v1.0.17 同步 · 更新于 2026-10-26
更新记录 (1)
-
v1.0.17
2026-10-26
修复同步逻辑
QQ官方交流群