海洋 CMS 远程图片本地化怎么批量处理

域名注册
域名注册 正式会员超兽战士 👑年卡会员
发布于 2026-10-08 10:17 ·2 浏览 ·0 回复

海洋 CMS 的远程图片本地化只有两条路:还没入库的内容,在采集节点的保存设置里把「图片本地化 / 下载远程图片」打开,采集的同时就落地到本地;已经入库的旧文章,后台没有一键批量按钮,只能自己写脚本按批次刷一遍数据库里的正文 HTML。**结论:能改采集规则就别事后补救,必须补的时候用 PHP 脚本 + 分批 SQL 处理,一次跑 100 条最稳。**

为什么采集时就开图片本地化,比事后补救省事?

结论:采集阶段开本地化,图片只下载一次;事后补救要把整站正文重新解析、重新下载,工作量和失败率都翻倍。

采集入库时,海洋 CMS 拿到的是目标站的 HTML,图片链接还是对方的域名。这时候打开本地化,程序会边入库边把图下载到 uploads/(或你配置的图片目录)并替换成站内路径,整个过程一次完成。等到文章已经躺在库里几个月,对方站换了域名、删了图、加了防盗链,你再去下载,能救回来的比例就低很多——尤其是图片站、影视站这类采集量大、原站不稳定的场景。

另外一个现实问题是:事后补的时候,你得先确认哪些文章还挂着远程图。用一条 SQL 就能数出来:

SELECT COUNT(*) FROM sea_data WHERE d_content LIKE '%src="http%';

这个数字就是你要处理的总量,跑之前先记下来,跑完再查一次对比。

海洋 CMS 采集节点里怎么开启图片本地化?

结论:入口在采集节点(采集规则)的保存/图片相关设置项里,勾上「下载远程图片」并确认图片保存目录可写。

具体操作顺序是:后台进采集管理,打开你正在用的采集节点,找到保存设置里的图片选项,把远程图片下载开关打开;同时确认服务器上图片目录权限是 755(部分环境用 777),PHP 的 curl 扩展或 allow_url_fopen 至少有一个是开的。配置好后先跑一次采集测试,抓 5 到 10 条,去前台看图片地址是不是已经变成自己域名下的路径。

需要注意两点:一是采集节点如果有多个,每个都要单独设置,改一个不会同步到其它节点;二是新采集的内容才会走本地化,历史数据不受影响,这也是为什么老站必须单独补一遍。

已经入库的文章,怎么用脚本批量本地化?

结论:写一个 PHP CLI 脚本,每轮取 100 条含远程图的记录,正则抓出 <img src>,用 curl 下载到本地目录后替换链接并回写数据库。

核心代码大致如下(表名和字段以你自己库里的实际结构为准,先在 phpMyAdmin 里 DESCRIBE sea_data 确认):

<?php
set_time_limit(0);
ignore_user_abort(true);
$pdo = new PDO('mysql:host=127.0.0.1;dbname=yourdb;charset=utf8mb4','user','pass');
$saveDir = __DIR__.'/uploads/localimg/';
if (!is_dir($saveDir)) mkdir($saveDir, 0755, true);

while (true) {
    $rows = $pdo->query("SELECT d_id,d_content FROM sea_data
        WHERE d_content LIKE '%<img%http%' LIMIT 100")->fetchAll(PDO::FETCH_ASSOC);
    if (!$rows) break;
    foreach ($rows as $row) {
        $content = $row['d_content'];
        preg_match_all('/<img[^>]+src=["\'](https?:\/\/[^"\']+)["\']/i', $content, $m);
        foreach ($m[1] as $url) {
            $ext  = pathinfo(parse_url($url, PHP_URL_PATH), PATHINFO_EXTENSION) ?: 'jpg';
            $name = md5($url).'.'.$ext;
            $file = $saveDir.$name;
            if (!file_exists($file)) {
                $ch = curl_init($url);
                curl_setopt_array($ch, [
                    CURLOPT_RETURNTRANSFER => true,
                    CURLOPT_TIMEOUT        => 20,
                    CURLOPT_FOLLOWLOCATION => true,
                    CURLOPT_REFERER        => 'https://你的域名/',
                    CURLOPT_USERAGENT      => 'Mozilla/5.0',
                    CURLOPT_SSL_VERIFYPEER => false,
                ]);
                $data = curl_exec($ch);
                if ($data) file_put_contents($file, $data);
                curl_close($ch);
            }
            $content = str_replace($url, '/uploads/localimg/'.$name, $content);
        }
        $pdo->prepare("UPDATE sea_data SET d_content=? WHERE d_id=?")->execute([$content, $row['d_id']]);
    }
}

这里有个设计上的小技巧:WHERE ... LIKE '%<img%http%' 加上固定的 LIMIT 100(不带 OFFSET),处理完的这条记录链接已经被替换成 /uploads/...,不再匹配条件,下一轮自然取到的是新的 100 条。这样脚本天然幂等,中断了重跑也不会重复处理。

用 php localize.php 在命令行跑,别在浏览器里打开——浏览器有 30 秒执行时间限制,命令行不受影响。

批量本地化最容易踩的坑有哪些?

结论:防盗链、超时、图片下载失败导致死循环,是三个最高频的问题,前两个加参数就能解决,第三个要加保护。

  • 防盗链:目标站校验 Referer,不传就返回 403 或一张占位图。上面代码里的 CURLOPT_REFERER 就是干这个的,填你站点的域名即可。
  • HTTPS 证书:老服务器 CA 证书过期会直接失败,加 CURLOPT_SSL_VERIFYPEER => false 绕过。
  • 死循环保护:如果某条记录的图片全部下载失败,链接没被替换,它会一直匹配条件。建议加一个计数器,比如连续 3 轮查出来的 d_id 完全一样就 break,或者给失败记录打标记跳过。
  • 先备份:跑之前 mysqldump -u user -p yourdb > backup.sql,先只处理 10 条验证替换后的前台显示正常,再放开跑全量。
  • CDN 与路径:如果站内用了 CDN 或图片走独立域名,替换后的路径要跟着改成对应的绝对地址,否则前台会 404。

跑完全量后,再执行一次开头那条 SELECT COUNT(*),数字降到接近 0 就说明处理干净了。剩下的个位数记录,基本是原图已被删除的,直接手动换成站内占位图即可。

版权声明:本文来自 GJ站长论坛《海洋 CMS 远程图片本地化怎么批量处理》
原文链接:https://www.gj0.com/thread-894.html
转载请注明出处并保留本声明;内容仅代表作者观点,与本站立场无关。若本文涉嫌侵权,请联系本站处理。

全部回复 0

还没有回复,来抢沙发~