My Computer · 2025/09/04 4

苹果cms 重复视频合并插件 可多规则筛选

2025-10-16 更新:

更新1:支持模糊搜索,当不选择任何重复规则时则按关键字进行模糊搜索,手动选择需要合并的视频和目标视频。

更新2:因为经常清理重复视频,所以会导致大量的404页面,这是近一个月404的访问量,为了挽救可怜的流量,挽留住每一个用户,所以给404做了升级,合并/删除下线的视频自动跳转到新的url,避免产生404。

比如视频id 162327 和 161401 合并为 161401 ,这样访问 http://*.com/voddetail/162327.html 时 会自动跳转到新的url地址:http://*.com/voddetail/161401.html

建一个映射表:用于“老→新”的确定性跳转,命中就直接 301。

CREATE TABLE IF NOT EXISTS `mac_redirect` (
  `id` BIGINT UNSIGNED NOT NULL AUTO_INCREMENT,
  `old_path` VARCHAR(512) NOT NULL,         -- 仅存相对路径,如 /voddetail/123.html
  `new_path` VARCHAR(512) NOT NULL,         -- 目标相对路径,如 /voddetail/987.html
  `http_code` SMALLINT UNSIGNED NOT NULL DEFAULT 301,
  `note` VARCHAR(255) DEFAULT NULL,
  `updated_at` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`),
  UNIQUE KEY `uk_old_path` (`old_path`),
  KEY `idx_updated_at` (`updated_at`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;

Nginx 加上 error_page 404 = @soft_404_guard 片段(放到 server{},别放到某个 location 里)

# 把所有 404 交给 @soft_404_guard
error_page 404 = @soft_404_guard;

# PHP:拦截上游返回的 404,才能触发 error_page
location ~ \.php$ {
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_pass 127.0.0.1:9000;   # 按你的 php-fpm 实际地址改
    fastcgi_intercept_errors on;   # ★ 必开,否则 PHP 的 404 不会进 error_page
}

# 404 守卫:先尝试“映射跳转”,失败再渲染你的 /label/404.html
location @soft_404_guard {
    internal;

    # ① 对 /voddetail|/vodplay 这类业务路径,先交给 Guard 做映射表跳转
    if ($request_uri ~ "^/(voddetail|vodplay)/") {
        rewrite ^ /api/404-guard.php?u=$request_uri last;
    }

    # ② 其余 404,直接渲染你做好的 404 页面(保持 404 状态)
    #    走 / -> try_files -> /index.php,模板会被正常解析
    rewrite ^ /label/404.html last;
}

新建 404 守卫脚本(可直接放到 /api/404-guard.php

function soft404() 中需要配置两个参数,请根据实际情况修改

代码更新:

404守卫 /api/404-guard.php
视图 application/admin/view/merge_vod/index.html
控制器 application/admin/controller/MergeVod.php


2025-10-11 更新:

增加豆瓣ID、审核状态筛选项;
取消默认名称+年份的兜底规则,改为完全按照前端的选择来进行筛选;

可以完全取代系统自带的”重名视频数据“合并功能

视图 application/admin/view/merge_vod/index.html
控制器 application/admin/controller/MergeVod.php


有的资源站喜欢视频名称后边加上年份,导致视频大量重复,苹果cms自带重名合并对这种情况又束手无策。。。

所以,增加一个专门针对视频名称+年份的清洗插件。插件会清洗片名末尾的年份(如“上海滩1983”、“上海滩(1983)”),并按勾选的字段(名称、年份、分类、地区、语言、演员、导演)组成入库去重键。
比如:上海滩 和 上海滩1983(两个视频年份均为 1983)将被视为同一视频,归并为“上海滩”。

本来打算在源头采集阶段就直接去重合并,老出错,先临时这样凑合着吧。

两段式去重

  1. 亡羊补牢(库内合并):把标题里带年份的重复视频(如“角斗士(2011) / 角斗士 2011 / 角斗士[2011]”)按“清洗后片名 + 年份”等规则分组、预览、选择并合并,将播放地址去重并并入“最干净”的目标条目。兼容不带年份和各种符号变体。
  2. 源头治理(采集阶段):在入库前由 VodIngestGuard 计算去重键 dedup_key(默认:名称+年份,可叠加分类/地区/语言/演员/导演),命中则直接合并,未命中则新建,并回填 dedup_key,后续命中更快更稳。

主要功能点(库内合并)

  • 筛选与分组:点击“筛选”后再扫描;支持关键字、分类ID范围、显示范围(活动/已忽略/全部)。
  • 入库重复规则(库内):可选项——名称、分类、年份、地区、语言、演员、导演(默认名称+年份)。
  • 候选条目多选:每个分组内可多选具体条目,默认全选;用于剔除“看起来相似但不该合并”的个例。
  • 忽略分组:一键忽略 / 取消忽略;支持只看“已忽略”。忽略信息存储在 merge_vod_ignore 表。
  • 建议目标选择:优先“干净名=片名且(若可)年份匹配”的条目;否则按标题长度最短、再按ID。
  • 播放合并:逐播放器合并,并按 [分集名 + URL] 去重;维持 $$$ / # / $ 规范;统计新增/跳过数。
  • 执行策略
    • 合并后下线来源删除来源二选一互斥)。
    • 事务 + 行级锁,防并发脏写。
    • 分页参数、筛选规则、分组键在“下一页”时原样携带
    • 连接控制:批处理后 Db::close(),缓解 max_user_connections

主要功能点(采集阶段守卫)

  • VodIngestGuardapp/common/service/VodIngestGuard.php
    • 自动读取后台配置 collect.ingest_rules(在“采集设置”中勾选),无配置则回落“名称+年份”。
    • 构造 dedup_key:按勾选字段生成(name、cat、year、area、lang、actor、director)。
    • 命中路径:先用 dedup_key 命中 → 若老数据尚未写入 dedup_key,执行兼容命中(清洗后片名 + 年份 + 可选维度),命中后回填 dedup_key
    • 合并策略:合并播放并去重;preferCleanName=true 时,如目标标题不是干净名而新数据可清洗出干净名,则用干净名覆盖;其他字段“只在目标为空时补齐”,更温和。
    • 并发安全:整条流程包裹事务,并对命中行 FOR UPDATE 加锁。
    • 结构自检:自动添加 dedup_key 字段与索引 idx_dedup_key(可后续手动升级为 UNIQUE)。
  • Collect.php 改造
    • 新增 vod_data_guard():按配置驱动守卫入库;?guard=0 可临时关闭回退原逻辑。
    • 将资源字段映射到 vod_* 规范;分页输出与原行为一致。

后台配置与表单

  • 采集设置页(application/admin/view/system/configcollect.html ):新增 入库重复规则(针对年份) 多选框(名称/分类/年份/地区/语言/演员/导演),默认勾选 名称 + 年份;说明“如 上海滩上海滩1983(年份均为 1983)将合并为‘上海滩’”。
  • Collect::info() 保存:读写 collect[ingest_rules][name|year|...]APP_PATH/extra/collect.php,供 Guard 读取。

新增忽略分组表 mac_merge_vod_ignore

用途:库内合并页面里“忽略/取消忽略”某个分组(例如名称+年份),避免反复出现。

CREATE TABLE IF NOT EXISTS `mac_merge_vod_ignore` (
  `id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
  `grp_key` VARCHAR(255) NOT NULL COMMENT '分组键(如 name:xxx||year:2021...)',
  `note` VARCHAR(255) NOT NULL DEFAULT '' COMMENT '备注',
  `ctime` TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
  PRIMARY KEY (`id`),
  UNIQUE KEY `uniq_grp_key` (`grp_key`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='合并工具-忽略分组';

说明

  • 该表会在页面控制器 MergeVod::ensureIgnoreTable() 首次访问时自动尝试创建;无 CREATE 权限则需手工执行。
  • grp_key 与页面上显示的“分组键”一致,例如:name:上海滩||year:1983(也可能包含分类/地区/语言/演员/导演字段,取决于你的分组规则)。

历史数据处理页面,入口:/admin.php/admin/merge_vod/index.html

后台设置页面:

采集时合并处理结果

文件清单:
application/common/service/VodIngestGuard.php
application/admin/controller/Collect.php

application/admin/view/system/configcollect.html
视图 application/admin/view/merge_vod/index.html
控制器 application/admin/controller/MergeVod.php

已经修改好的文件,供参考。