牛马论坛查看原帖 →

图录 · Archive — 部署与使用教程

七夏 15 阅读 1 回复
[size=5][b]图录 · Archive — 部署与使用教程[/b][/size]

[size=3][b]目录[/b][/size]
1. 项目简介
2. 环境要求
3. 部署步骤
4. config.php 配置详解
5. 后台使用教程
6. 前台访问
7. 定时任务配置(宝塔面板)
8. 常见问题 Q&A
9. 注意事项(安全 / 运维)

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]一、项目简介[/b][/size]

「图录 · Archive」是一套自动化图片采集归档系统,工作流程:
[list=1]
[*]定时采集目标站点的帖子(标题 / 描述 / 图片列表)
[*]下载完整图片,生成 5 张预览图
[*]打包 ZIP,自动上传至蓝奏云网盘
[*]前台以瀑布流卡片展示,访客可在线浏览预览并下载完整套图
[/list]
特性:
[list]
[*]fsockopen 异步触发 worker,无需 exec 权限
[*]支持多广告位随机轮换(Google AdSense 友好)
[*]AES-256-CBC 加密下载链接,服务端解密跳转
[*]CSRF 防护 + Session 安全配置
[*]全链路 SSL 证书校验
[*]蓝奏云 cookie 失效自动检测、钉钉机器人通知
[*]任务卡死自动恢复(重置状态 / 强制杀进程)
[*]进度持久化(flock 文件锁),定时任务防重叠
[/list]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]二、环境要求[/b][/size]

[b]必须:[/b]
[list]
[*]PHP 8.0+(推荐 8.1 / 8.2)
[*]PHP-FPM 模式(不推荐 mod_php)
[*]扩展:curl、openssl、gd、mbstring、json、zip
[*]MySQL 不需要(数据全部走文件存储)
[*]Web 服务器:Nginx 推荐,Apache 也可
[*]HTTPS 证书(强烈推荐 Let's Encrypt 免费证书)
[/list]
[b]可选:[/b]
[list]
[*]宝塔面板(便于配置定时任务和管理 PHP)
[*]钉钉机器人(cookie 失效推送告警)
[*]Google AdSense 广告位
[/list]
[b]系统 CA 证书:[/b]
[list]
[*]Debian/Ubuntu:apt install ca-certificates
[*]CentOS/RHEL:yum install ca-certificates
[*]宝塔面板:默认已自带,路径 /etc/ssl/certs/ca-certificates.crt
[*]macOS:/etc/ssl/cert.pem
[/list]
[code]# 验证 PHP 是否满足要求
php -m | grep -E 'curl|openssl|gd|mbstring|zip'
# 应输出 curl / openssl / gd / mbstring / zip 五项[/code]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]三、部署步骤[/b][/size]

[b]1. 上传项目文件[/b]

将整个项目目录上传到站点根目录,例如:
[code]/www/wwwroot/你的站点/[/code]
目录结构:
[code]├── public/ # Web 可访问目录(Nginx root 指向此)
│ ├── admin.php # 后台管理界面
│ ├── index.php # 前台首页
│ ├── post.php # 帖子详情页
│ ├── dl.php # 下载跳转(服务端解密)
│ ├── view.php # 单帖 JSON 接口
│ └── preview.php # 预览图代理
├── src/ # 业务类(不对外暴露)
├── data/ # 状态/密钥/cookie(自动创建)
├── downloads/ # 本地 ZIP 临时存放
├── tmp/ # 临时文件
├── config.php # 主配置文件
├── cron.php # 定时任务入口
└── worker.php # 后台 worker 入口[/code]
[b]2. 设置目录权限[/b]

[code]cd /www/wwwroot/你的站点/
mkdir -p data downloads tmp data/previews
chmod -R 755 .
chmod -R 777 data downloads tmp
chown -R www:www .[/code]
[b]3. 配置 Nginx[/b]

关键:root 必须指向 [b]public/[/b] 目录,否则 src/、config.php 会被外部访问到。

[code]server {
listen 443 ssl http2;
server_name 你的域名;

ssl_certificate /path/to/fullchain.pem;
ssl_certificate_key /path/to/privkey.pem;

root /www/wwwroot/你的站点/public;
index index.php;

# 防止访问敏感文件
location ~ /\.(ht|git|env) {
deny all;
}
location ~ ^/(config|worker|cron)\.php$ {
deny all;
}
location ~ ^/(src|data|downloads|tmp)/ {
deny all;
}

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
fastcgi_pass unix:/tmp/php-cgi-80.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
# 关键:worker 需要长连接,避免被 fastcgi 超时杀掉
fastcgi_read_timeout 3600s;
fastcgi_param HTTPS on;
}
}[/code]
[b]4. 设置站点访问密码[/b]

用 PHP CLI 生成 bcrypt 哈希:
[code]php -r "echo password_hash('你的密码', PASSWORD_BCRYPT), PHP_EOL;"[/code]
将输出的哈希填入 config.php 的 [b]auth_password_hash[/b] 字段。

[b]5. 设置 HTTPS(重要)[/b]

由于启用了 SSL 证书校验,所有 HTTPS 出站请求都需要 CA 证书包。如果系统已有 CA 证书,无需额外配置;否则请安装 ca-certificates 包。

fsockopen 触发 worker 走 HTTPS 端口 443 + TLS,配置项:
[code]'worker_trigger_port' => 443,
'worker_trigger_tls' => true,[/code]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]四、config.php 配置详解[/b][/size]

打开 config.php,按需修改以下字段:

[b]1. 基础配置[/b]
[code]// 目标站点(默认采集站点,按需修改)
'base_url' => '采集站点地址',

// 鉴权密码哈希(必填!否则后台无密码)
'auth_password_hash' => '$2y$10$xxxxxx...',

// 采集首页数(1=只抓第一页,null=全部)
'max_list_pages' => 1,

// 请求间隔(秒)— 防止被目标站点封 IP
'list_interval' => 1.0,
'detail_interval' => 0.5,
'image_interval' => [1, 2],[/code]
[b]2. Worker 触发方式(推荐 fsockopen)[/b]
[code]// fsockopen 模式:无需 exec,由 PHP-FPM 进程托管
'worker_mode' => 'fsockopen',

// HTTPS 站点用 443 + true
'worker_trigger_port' => 443,
'worker_trigger_tls' => true,

// 触发 token 自动生成并存到 data/worker_token.json
'worker_token' => '',[/code]
[b]3. 蓝奏云上传[/b]
[code]'lanzou' => [
'enable' => true,
'cookie' => '', // 初始 cookie 可填这里或后台更新
'cookie_file' => __DIR__ . '/data/lanzou_cookie.txt',
'folder_prefix' => 'archive_', // 月度文件夹前缀,会生成 archive_2026-07
'delete_after_upload' => true, // 上传成功后删除本地 ZIP
'retry' => 3,
'interval' => 3.0,
],[/code]
[b]4. 钉钉通知(可选)[/b]
[code]'notifications' => [
'enable' => false, // 改为 true 启用
'dingtalk' => [
'webhook' => 'https://oapi.dingtalk.com/robot/send?access_token=xxx',
'secret' => 'SECxxx', // 加签密钥
'at_all' => false,
'at_mobiles' => [],
],
],[/code]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]五、后台使用教程[/b][/size]

访问 [code]https://你的域名/admin.php[/code]
[b]01 控制台[/b]
[list]
[*][b]启动[/b] — 开始采集(异步触发 worker,立即返回)
[*][b]停止[/b] — 写入 stop.flag 文件,worker 主循环检测到后优雅停止
[*][b]关闭进程[/b] — 强制 pkill worker 进程(卡死时使用)
[*][b]重置状态[/b] — 清除 status.json + stop.flag,状态切回待机(不删 ZIP 和归档)
[*][b]清空归档[/b] — 删除所有本地 ZIP(保留采集去重记录)
[/list]
[b]02 错误[/b] — 出现错误时自动展开,显示带时间戳的错误列表。

[b]03 运行日志[/b] — 实时滚动显示 worker 输出,2 秒自动刷新。

[b]04 归档文件[/b]
[list]
[*]每页 20 条,可翻页
[*]显示标题 / 采集时间 / 预览图数量 / 蓝奏云链接 / 本地 ZIP 状态
[*]「重试上传」按钮 — 一键重新上传所有本地保留的 ZIP(cookie 更新后使用)
[/list]
[b]05 Cookie 与通知[/b]
[list]
[*]粘贴新 cookie 后点击 [b]保存并验证[/b] — 写入 data/lanzou_cookie.txt 并立即调用 doupload.php?task=19 验证有效性
[*][b]保存并重试上传[/b] — 保存 cookie 后立即触发重试上传任务
[*][b]测试钉钉[/b] — 发送测试消息验证钉钉机器人配置
[/list]
[b]06 广告位[/b]
[list]
[*]5 个 slot:list_top / list_mid / list_bottom / post_top / post_bottom
[*]外加 analytics slot:用于 Google Analytics 等统计代码(前台 <head> 输出)
[*][b]list_mid 支持多广告轮换[/b]:在 textarea 中用空行分隔多个广告代码,前台每次插入时随机选一个
[*]建议:list_top 放 AdSense 全局库加载代码,list_mid / list_bottom 只放 <ins> + (adsbygoogle=...).push({})
[/list]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]六、前台访问[/b][/size]

[b]首页:[/b] [code]https://你的域名/[/code]
[list]
[*]瀑布流卡片布局,PC 端 6 列、平板 3 列、移动 2 列
[*]无限滚动加载(每页 20 条)
[*]图片懒加载(IntersectionObserver)
[*]每 12 张卡片内随机插入一个 list_mid 广告位
[/list]
[b]详情页:[/b] [code]https://你的域名/post.php?id=xxx[/code]
[list]
[*]显示 5 张预览图(懒加载)
[*]帖子标题 / 描述 / 下载按钮
[*]可分享的永久链接
[/list]
[b]下载流程:[/b]
[list]
[*]访客点击「下载完整套图」→ 跳转到 /dl.php?token=xxx
[*]dl.php 服务端解密 token + 校验有效期 + 校验 URL 域名
[*]302 重定向到蓝奏云下载页
[*]AES 密钥永不下发客户端,无法被反编译窃取
[/list]
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]七、定时任务配置(宝塔面板)[/b][/size]

[b]推荐配置:每天凌晨 3:17 执行一次[/b]

宝塔面板 → 计划任务 → 添加任务:
[list]
[*]任务类型:[b]Shell 脚本[/b]
[*]任务名称:图录采集
[*]执行周期:每天 3 时 17 分
[*]脚本内容:[code]/usr/bin/php /www/wwwroot/你的站点/cron.php >> /www/wwwroot/你的站点/data/cron.log 2>&1[/code]
[/list][b]cron.php 三种执行模式:[/b]
[list]
[*][code]php cron.php[/code] — 智能模式(推荐)。仅当空闲时启动采集;已完成时自动重试上传;都已处理则退出码 2
[*][code]php cron.php --force[/code] — 强制模式,忽略 running 状态直接启动(慎用)
[*][code]php cron.php --check[/code] — 仅检查状态不启动
[*][code]php cron.php --retry-upload[/code] — 仅触发重试上传
[/list]
[b]智能模式行为:[/b]
[list]
[*]状态 = running → 跳过本次(防重叠)
[*]状态 = idle / done / error → 启动采集
[*]状态 = done 且所有帖子已采集 + 有待重试 ZIP → 自动调用 retryUploads()
[*]状态 = done 且无待重试 ZIP → 退出码 2(避免空跑)
[/list]
[b]提示:[/b]fsockopen 触发的 worker 在 PHP-FPM 中后台运行,cron.php 仅负责触发,不阻塞。但若用 exec 模式,cron.php 会同步等待 worker 跑完。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]八、常见问题 Q&A[/b][/size]

[b]Q1:启动后状态一直显示「启动采集...」,worker 没运行起来?[/b]

A:检查以下几点:
[list=1]
[*]data 目录权限是否 777(worker_token.json 需要写入)
[*]fsockopen 连接是否成功:错误信息会显示 [code]resp=BAD[/code],看 resp_body 字段
[*]HTTPS 站点必须设置 [code]worker_trigger_port=443 + worker_trigger_tls=true[/code]
[*]查看 data/worker.log 是否有 PHP 错误
[*]宝塔面板 → 软件商店 → PHP → 禁用函数,确认 [code]fsockopen[/code] 没被禁用
[/list]
[b]Q2:worker 运行到一半卡住不动了?[/b]

A:先尝试 [b]停止[/b] 按钮(优雅停止)。如果 5 分钟后仍卡住:
[list=1]
[*]点击 [b]关闭进程[/b] 按钮(pkill 强制杀掉 worker.php 进程)
[*]点击 [b]重置状态[/b] 按钮清掉 status.json + stop.flag
[*]重新点击 [b]启动[/b]
[/list]
[b]Q3:蓝奏云 cookie 失效,所有上传都失败怎么办?[/b]

A:
[list=1]
[*]登录 [url=https://pc.woozooo.com/]https://pc.woozooo.com/[/url]
[*]浏览器 F12 → Network → 任意请求 → Request Headers → 复制完整 cookie 字段(需含 ylogin 和 phpdisk_info)
[*]后台 → Cookie 与通知 → 粘贴到 textarea → 点击 [b]保存并重试上传[/b]
[*]cookie 验证通过后会自动触发重试上传所有本地保留的 ZIP
[/list]
[b]Q4:cookie 更新后定时任务会自动重试上传吗?[/b]

A:会。cron.php 智能模式检测到 [code]state=done 且所有帖子已采集[/code] 时,会自动扫描本地是否有待上传 ZIP(upload_failed 或 lanzou_url 为空且 ZIP 存在)。如果有则自动调用 retryUploads()。

[b]Q5:归档列表很长,加载慢怎么办?[/b]

A:后台归档表已分页(每页 20 条)。前台首页已实现无限滚动,每次只加载 20 条。

[b]Q6:下载链接为什么有时效?能永久吗?[/b]

A:下载 token 有效期 1 小时(time() + 3600),过期后访客需重新访问详情页获取新 token。这是为了防止 token 被批量爬取。如需修改时效,编辑 [code]public/post.php[/code] 第 47 行的 [code]time() + 3600[/code]。

[b]Q7:移动端访问需要点两次才能打开详情页?[/b]

A:已修复。早期版本因 iOS Safari 的 hover trap,第一次 tap 只切换 :hover 状态。已用 [code]@media (hover: hover)[/code] 包裹所有 hover 规则解决。

[b]Q8:返回顶部按钮不显示?[/b]

A:已修复。早期版本按钮 HTML 写在 <script> 标签内被浏览器忽略,现已将按钮移到 </script> 之后。向下滚动 400px 后会自动出现。

[b]Q9:标题中有 [秀人付费] 这种标记怎么办?[/b]

A:已自动清除。采集时 cleanTitle() 会移除所有 [xxx] 和 【xxx】 格式标记。同时在标题末尾追加图片数量后缀(如 [code]+ 80P[/code])。

[b]Q10:如何关闭采集但保留前台访问?[/b]

A:把 config.php 的 [code]max_list_pages[/code] 改为 0 或在宝塔禁用 cron 任务即可。worker 不会主动启动(除非手动点击后台「启动」按钮)。前台已有的归档记录不受影响。

[b]Q11:如何删除所有采集记录重新开始?[/b]

A:直接删除以下文件:
[code]rm -f data/status.json data/progress.json
rm -rf downloads/*
rm -rf data/previews/*[/code]
[b]Q12:fsockopen 模式和 exec 模式有什么区别?[/b]

A:
[list]
[*][b]fsockopen[/b](推荐):通过 HTTP 自调用 admin.php?action=run_worker 触发 worker。worker 在 PHP-FPM 进程中运行,无需 exec 权限,无需查找 PHP CLI 路径。需要 HTTPS 端口可达。
[*][b]exec[/b](备用):通过 [code]nohup php worker.php &[/code] 直接启动 CLI 进程。需要 exec 函数可用 + 正确的 PHP CLI 路径([code]php_binary[/code])。
[/list]
[b]Q13:定时任务执行失败,提示「找不到 PHP CLI」?[/b]

A:宝塔面板的 PHP CLI 路径通常是 [code]/www/server/php/80/bin/php[/code](80 是版本号)。在 config.php 中设置:
[code]'php_binary' => '/www/server/php/80/bin/php',[/code]
[b]Q14:上传到蓝奏云的 ZIP 找不到分享链接?[/b]

A:检查后台日志中是否有 [code]无法解析分享链接[/code] 错误。可能是蓝奏云接口返回格式变化。临时解决:到蓝奏云后台手动获取分享链接,更新到 data/progress.json 对应记录的 [code]lanzou_url[/code] 字段。

[b]Q15:前台广告位不显示?[/b]

A:
[list=1]
[*]确认广告代码已保存(后台 → 广告位 → 保存)
[*]确认 AdSense 账户已激活(新账户需先有访问量才能显示广告)
[*]浏览器 F12 控制台查看是否有报错
[*]list_top 必须放 AdSense 全局库加载代码 [code]<script async src="...adsbygoogle.js">[/code]
[/list]━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]九、注意事项[/b][/size]

[b]【安全相关】[/b]

[list=1]
[*][b]后台密码必须设置[/b]。config.php 的 [code]auth_password_hash[/code] 留空等于无密码,任何人都能进入后台。
[*][b]data 目录不要对外暴露[/b]。Nginx 必须配置 [code]location ~ ^/data/ { deny all; }[/code],否则 aes.key / lanzou_cookie.txt / status.json 都会被外部访问到。
[*][b]config.php 不要对外暴露[/b]。同样用 [code]location ~ ^/config\.php$ { deny all; }[/code] 拦截。
[*][b]src 目录不要对外暴露[/b]。业务类代码泄露会被黑产分析利用。
[*][b]AES 密钥永不下发[/b]。dl.php 已改为服务端解密 + 302 跳转,密钥仅存于 data/aes.key,外部无法获取。请勿自行修改为前端解密方案。
[*][b]SSL 证书校验已启用[/b]。所有 cURL 出站请求(蓝奏云 / 钉钉 / 目标站点 / 图片下载)都启用 VERIFYPEER + VERIFYHOST,防止中间人攻击。如目标站点使用自签证书,请将证书加入系统 CA 包或临时回退 false(不推荐生产环境)。
[*][b]CSRF 防护已启用[/b]。后台所有 POST 接口都校验 csrf_token,前端 JS 已自动附带。请勿删除 [code]checkCsrf()[/code] 调用。
[*][b]run_worker 端点限制本地 IP[/b]。仅 127.0.0.1 / ::1 可访问,防止 token 泄漏后被远程利用。
[*][b]worker_token 自动生成[/b]。首次启动时随机生成 32 字符 hex 存到 data/worker_token.json。请勿手动泄露。
[*][b]Session 安全配置[/b]。httponly 防 JS 读取,secure 在 HTTPS 下启用,SameSite=Lax 防 CSRF。登录成功后 session_regenerate_id(true) 防 session fixation。
[/list]
[b]【运维相关】[/b]

[list=1]
[*][b]定时任务必须用绝对路径[/b]。宝塔 Shell 脚本中 PHP 路径用 [code]/www/server/php/80/bin/php[/code],不要依赖 PATH。
[*][b]fsockopen 模式下 cron.php 仅触发[/b]。cron.php 会调用 admin.php?action=run_worker,但通过 fsockopen 异步触发后会立即返回,不阻塞 cron 任务。
[*][b]cron 重叠保护[/b]。cron.php 检测 state=running 时直接退出,不会重复触发 worker。同一次 cron 触发新 worker 时也会先清理 stop.flag。
[*][b]cookie 失效后本地 ZIP 保留[/b]。上传失败的 ZIP 不会被删除,等 cookie 更新后可一键重试上传。
[*][b]月度文件夹自动创建[/b]。蓝奏云每月会自动新建 archive_YYYY-MM 文件夹,无需手动操作。
[*][b]归档记录去重[/b]。data/progress.json 中保存已采集的帖子 ID。重复采集时同一帖子不会重复下载。如需强制重采某帖,需手动删除 progress.json 中对应记录。
[*][b]停止标志文件[/b]。点停止按钮会创建 data/stop.flag。worker 主循环和图片下载循环每张图都会检查此文件。强制重置状态时会自动清除。
[*][b]磁盘空间[/b]。每套图片平均 10-50MB,本地 ZIP 上传成功后会自动删除(delete_after_upload=true)。但失败的 ZIP 会保留,建议定期检查 downloads 目录大小。
[*][b]worker.log 大小[/b]。data/worker.log 仅记录最后一次启动的错误输出,启动前会被清空。
[*][b]预览图存储位置[/b]。预览图在 data/previews/<post_id>/ 下,不存放于 public/。通过 public/preview.php?id=xxx&n=N 代理访问,避免直接暴露目录结构。
[/list]
[b]【合规相关】[/b]

[list=1]
[*]本系统仅用于个人归档管理。请确保采集行为符合目标站点的 robots.txt 和服务条款。
[*]前台广告位如使用 Google AdSense,请确保 AdSense 政策合规(不投放侵权内容广告等)。
[*]下载链接有效期 1 小时 + AES 加密,但仍请定期检查是否有异常访问模式。
[*]请勿将本系统用于商业转售他人版权内容。
[/list]
[b]【性能相关】[/b]

[list=1]
[*]采集间隔已默认保守设置(1-2 秒),切勿改为 0 否则会被目标站封 IP。
[*]图片下载重试 3 次,每次递增 500ms 间隔。
[*]预览图压缩为 800px 宽度 + 80 质量,平衡大小与清晰度。
[*]前端无限滚动 + IntersectionObserver 懒加载,避免一次性加载所有图片。
[*]后台状态轮询每 2 秒一次,刷新会通过 8 秒超时保护避免 PHP-FPM worker 被占满。
[/list]
[b]【备份建议】[/b]

定期备份以下文件:
[list]
[*][code]config.php[/code] — 配置
[*][code]data/aes.key[/code] — AES 密钥(丢失后所有旧下载链接失效)
[*][code]data/worker_token.json[/code] — worker 触发 token
[*][code]data/lanzou_cookie.txt[/code] — 蓝奏云 cookie
[*][code]data/ad_slots.json[/code] — 广告位代码
[*][code]data/progress.json[/code] — 归档记录(最重要!包含所有帖子信息和蓝奏云链接)
[/list]
[b]无需备份[/b]:downloads/(ZIP 上传后已删)、data/previews/(可重新生成)、data/status.json(运行时状态)。

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━

[size=4][b]十、技术支持[/b][/size]

如遇问题,请按以下顺序自查:
[list=1]
[*]查看本教程 Q&A 部分
[*]查看后台运行日志和错误列表
[*]查看 data/worker.log 中的 PHP 错误
[*]查看 Nginx 错误日志:[code]/www/wwwlogs/你的域名.error.log[/code]
[*]查看宝塔 PHP 错误日志
[/list]
报告问题时请提供:
[list]
[*]后台状态截图(状态条 / 日志 / 错误列表)
[*]data/worker.log 内容
[*]config.php 配置(隐去密码哈希和 cookie)
[*]PHP 版本和已加载扩展
[/list]
[i]本教程最后更新:2026-07-19[/i]
宝塔面板的计划任务脚本可直接使用这个:
[code]/www/server/php/80/bin/php /www/wwwroot/站点目录/cron.php[/code]

阅读全文与全部回复 →