此方法适用于所有wordpress站点
要实现的目标:
- 当文章当中存在外链图片的时候则在发布或是更新文章的时候自动下载图片进行替换,并在文章列表当中调用该文章当中的第一张图像作为缩略图。
- 如果文章当中不存在外链图片,则随机调用指定目录当中的图片作为文章列表当中的缩略图。
附加功能:
- 自动重置图片名称。
- 检测网站所使用的HTTP协议,并保持一致。
- 检测文章当中的外链图像大小,如果过小或是不存在,则随机调用指定目录下的图像。
首次版本
代码
1,在wordpress当前主题函数functions.php的末尾空行处加上如下代码:
// 支持缩略图
if (function_exists('add_theme_support')) {
add_theme_support('post-thumbnails');
}
// 文章发布时自动下载外链图片并替换为本地图片
function custom_upload_remote_images_on_save($content) {
preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches);
if (!empty($matches[1])) {
$upload_dir = wp_upload_dir();
foreach ($matches[1] as $image_url) {
// 跳过已是本站图片
if (strpos($image_url, $upload_dir['baseurl']) === 0) continue;
$image = @file_get_contents($image_url);
if ($image === false) continue;
// 生成唯一安全文件名
$ext = pathinfo(parse_url($image_url, PHP_URL_PATH), PATHINFO_EXTENSION);
$filename = uniqid('img_') . '.' . $ext;
$local_image_path = $upload_dir['path'] . '/' . $filename;
// 保存图片到本地
file_put_contents($local_image_path, $image);
// 替换内容中的图片链接
$local_url = $upload_dir['url'] . '/' . $filename;
// 保证协议与站点一致
$local_url = set_url_scheme($local_url);
$content = str_replace($image_url, $local_url, $content);
}
}
return $content;
}
// 只在保存/发布文章时处理内容
function custom_upload_remote_images_on_save_post($post_id) {
// 防止自动保存、修订、自动草稿等
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;
$post = get_post($post_id);
if ($post->post_type != 'post' && $post->post_type != 'page') return;
remove_action('save_post', 'custom_upload_remote_images_on_save_post'); // 防止递归
$new_content = custom_upload_remote_images_on_save($post->post_content);
if ($new_content !== $post->post_content) {
wp_update_post([
'ID' => $post_id,
'post_content' => $new_content
]);
}
add_action('save_post', 'custom_upload_remote_images_on_save_post');
}
add_action('save_post', 'custom_upload_remote_images_on_save_post');
// 获取文章第一张图片作为缩略图,无则随机
function catch_first_image() {
global $post;
$first_img = '';
$image_width = 0;
if (isset($post->post_content) && preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches)) {
$first_img = $matches[1][0];
if (!empty($first_img)) {
$image_size = @getimagesize($first_img);
if ($image_size) {
$image_width = $image_size[0];
}
}
}
// 如果第一张图不存在或过小,则返回随机图片
if (empty($first_img) || $image_width < 50) {
$random = mt_rand(1, 62); // 你的随机图片数量
$first_img = get_stylesheet_directory_uri() . '/assets/images/random/' . $random . '.jpg';
$first_img = set_url_scheme($first_img);
} else {
// 保证协议与站点一致
$first_img = set_url_scheme($first_img);
}
return $first_img;
}
2,在wordpress当前使用的主题的文章列表模板当中的缩略图调用位置添加如下代码进行调用(先前的代码注释掉):
<img src="<?php echo esc_url(catch_first_image()); ?>" alt="<?php the_title_attribute(); ?>">
3,在当前使用的主题目录下面的/assets/images/目录下建立random目录,最终的路径是:/assets/images/random
(如果没有/assets/images/目录则手动按这个路径去新建目录。)
4,找到一组图片并上传到这个目录当中:/assets/images/random
这样的话,再去添加文章或是更新文章,代码就会生效了。
说明:
此代码并不会将下载的图片放入到wordpress默认的媒体库当中显示,下载的图片会存在于/wp-content/uploads的下级目录当中。
这么做的优点是:因为没有将图片放入wordpress默认的媒体库当中,也就导致下载的每一张图片都是唯一的,并不会存在多个尺寸的副本,大大节省了服务器硬盘的空间占用。
优化版本
说明:
此优化版本以基于前面的代码。
优化条目:
- 首次执行时,为所有历史无图文章分配并保存一个随机缩略图,后续不再变动。
- 检查文章当中无法下载的外链图片,如果无法下载则连带删除整个img标签及图片链接。
- 新文章,如果无图,也分配并保存一个随机缩略图。
- 文章列表上的文章缩略图不会连接调用相同的图像,随机调用的时候进行了判断和排除。
- 效率优化,避免每次页面刷新都重新分配,减少PHP、MySQL、Apache2、内存消耗。
代码:
1,在wordpress当前主题函数functions.php的末尾空行处加上如下代码:
// 支持缩略图
if (function_exists('add_theme_support')) {
add_theme_support('post-thumbnails');
}
// 指定随机图片目录和数量
define('RANDOM_IMG_DIR', '/assets/images/random/');
define('RANDOM_IMG_COUNT', 62);
// 下载图片并返回本地URL,失败返回false
function try_download_image($image_url) {
$upload_dir = wp_upload_dir();
$image = @file_get_contents($image_url);
if ($image === false) return false;
$ext = pathinfo(parse_url($image_url, PHP_URL_PATH), PATHINFO_EXTENSION);
if (!$ext) $ext = 'jpg';
$filename = uniqid('img_') . '.' . $ext;
$local_image_path = $upload_dir['path'] . '/' . $filename;
file_put_contents($local_image_path, $image);
$local_url = $upload_dir['url'] . '/' . $filename;
return set_url_scheme($local_url);
}
// 随机获取一张图片(可指定排除某一张)
function get_random_image_url($exclude = null) {
$rand = mt_rand(1, RANDOM_IMG_COUNT);
if ($exclude !== null && RANDOM_IMG_COUNT > 1) {
// 避免连续出现同一张
while ($rand == $exclude) {
$rand = mt_rand(1, RANDOM_IMG_COUNT);
}
}
$img_url = get_stylesheet_directory_uri() . RANDOM_IMG_DIR . $rand . '.jpg';
return set_url_scheme($img_url);
}
// 文章发布时自动下载外链图片并替换为本地图片,下载失败则删除标签并用随机图像替换
function custom_upload_remote_images_on_save($content) {
preg_match_all('/<img[^>]+src=["\']([^"\']+)["\'][^>]*>/i', $content, $matches);
if (!empty($matches[1])) {
$upload_dir = wp_upload_dir();
foreach ($matches[1] as $image_url) {
// 跳过已是本站图片
if (strpos($image_url, $upload_dir['baseurl']) === 0) continue;
$local_url = try_download_image($image_url);
if ($local_url) {
// 替换为本地图片
$content = str_replace($image_url, $local_url, $content);
} else {
// 下载失败,删除原img标签和链接,插入随机图片
// 删除包裹a标签的img
$pattern = '#<a[^>]*>\s*<img[^>]+src=["\']' . preg_quote($image_url, '#') . '["\'][^>]*>\s*</a>#i';
$content = preg_replace_callback($pattern, function($m) {
return '<img src="' . get_random_image_url() . '" alt="random">';
}, $content);
// 删除单独img标签
$pattern2 = '#<img[^>]+src=["\']' . preg_quote($image_url, '#') . '["\'][^>]*>#i';
$content = preg_replace_callback($pattern2, function($m) {
return '<img src="' . get_random_image_url() . '" alt="random">';
}, $content);
}
}
}
return $content;
}
// 只在保存/发布文章时处理内容
function custom_upload_remote_images_on_save_post($post_id) {
if (wp_is_post_autosave($post_id) || wp_is_post_revision($post_id)) return;
$post = get_post($post_id);
if ($post->post_type != 'post' && $post->post_type != 'page') return;
remove_action('save_post', 'custom_upload_remote_images_on_save_post');
$new_content = custom_upload_remote_images_on_save($post->post_content);
if ($new_content !== $post->post_content) {
wp_update_post([
'ID' => $post_id,
'post_content' => $new_content
]);
}
maybe_set_random_thumbnail($post_id, $new_content);
add_action('save_post', 'custom_upload_remote_images_on_save_post');
}
add_action('save_post', 'custom_upload_remote_images_on_save_post');
// 为无图文章分配随机缩略图(只分配一次)
function maybe_set_random_thumbnail($post_id, $content = null) {
if (get_post_meta($post_id, '_random_thumbnail', true)) return;
if (is_null($content)) {
$post = get_post($post_id);
$content = $post->post_content;
}
if (preg_match('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $content)) return;
$random_img = get_random_image_url();
update_post_meta($post_id, '_random_thumbnail', $random_img);
}
// 获取文章缩略图:优先第一张图,无则用已分配的随机图
function catch_first_image($exclude_random = null) {
global $post;
if (!$post) return '';
// 优先用文章内第一张图片
if (isset($post->post_content) && preg_match_all('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content, $matches)) {
$first_img = $matches[1][0];
if (!empty($first_img)) {
$image_size = @getimagesize($first_img);
if ($image_size && $image_size[0] >= 50) {
return set_url_scheme($first_img);
}
}
}
// 没有图片则用已分配的随机缩略图
$random_img = get_post_meta($post->ID, '_random_thumbnail', true);
if ($random_img) {
// 文章列表时可传入$exclude_random避免连续
if ($exclude_random) {
$current_num = intval(basename($random_img, '.jpg'));
if ($current_num == $exclude_random) {
$random_img = get_random_image_url($exclude_random);
}
}
return $random_img;
}
// 兼容历史文章未分配的情况
$random_img = get_random_image_url($exclude_random);
update_post_meta($post->ID, '_random_thumbnail', $random_img);
return $random_img;
}
// 文章列表循环时避免连续随机图像
// 用法示例:在循环外定义 $last_random = null; 在循环内 $img = catch_first_image($last_random); $last_random = intval(basename($img, '.jpg'));
//
// 首次激活时批量为历史无图文章分配随机缩略图
function batch_set_random_thumbnails_for_old_posts() {
$already_done = get_option('random_thumbnail_batch_done');
if ($already_done) return;
$args = array(
'post_type' => array('post', 'page'),
'post_status' => 'publish',
'posts_per_page' => -1,
'fields' => 'ids',
);
$posts = get_posts($args);
foreach ($posts as $post_id) {
$post = get_post($post_id);
if (get_post_meta($post_id, '_random_thumbnail', true)) continue;
if (preg_match('/<img.+src=[\'"]([^\'"]+)[\'"].*>/i', $post->post_content)) continue;
$random_img = get_random_image_url();
update_post_meta($post_id, '_random_thumbnail', $random_img);
}
update_option('random_thumbnail_batch_done', 1);
}
add_action('init', 'batch_set_random_thumbnails_for_old_posts');
2,主题模板当中的调用代码
(1)调用缩略图(优先文章内第一张图,无则用分配的随机图)
<img src="<?php echo esc_url(catch_first_image(isset($last_random) ? $last_random : null)); ?>" alt="<?php the_title_attribute(); ?>">
<?php $last_random = intval(basename(catch_first_image(isset($last_random) ? $last_random : null), '.jpg')); ?>
(2)完整示例(文章列表循环中)
<?php $last_random = null; ?>
<?php if (have_posts()) : while (have_posts()) : the_post(); ?>
<div class="post-item">
<img src="<?php echo esc_url(catch_first_image($last_random)); ?>" alt="<?php the_title_attribute(); ?>">
<?php $last_random = intval(basename(catch_first_image($last_random), '.jpg')); ?>
<h2><?php the_title(); ?></h2>
<!-- 其它内容 -->
</div>
<?php endwhile; endif; ?>
(3)单篇文章页
单篇文章页通常不用避免连续图像,直接:
<img src="<?php echo esc_url(catch_first_image()); ?>" alt="<?php the_title_attribute(); ?>">
(4)如果你想用 WordPress 的特色图像(Featured Image)优先
<?php if (has_post_thumbnail()) : ?>
<?php the_post_thumbnail('full'); ?>
<?php else : ?>
<img src="<?php echo esc_url(catch_first_image()); ?>" alt="<?php the_title_attribute(); ?>">
<?php endif; ?>
总结:
调用函数:catch_first_image($last_random)
参数:$last_random 用于避免列表中连续随机图像(可选,单篇文章不用)。
返回值:直接就是图片 URL,可用于 <img src=”…”>。
相关参数说明:
- 首次批量处理:batch_set_random_thumbnails_for_old_posts 只在第一次激活时运行一次,自动为历史无图文章分配随机缩略图,后续不再重复执行。
- 新文章处理:maybe_set_random_thumbnail 在每次保存/发布时只对无图文章分配一次随机缩略图。
- 前台展示:catch_first_image 优先用正文第一张图片,无则用已分配的随机缩略图,保证每篇无图文章的缩略图固定且只分配一次。
- 效率优化:所有分配和检查都只在保存/发布时进行,前台展示时只读取 post_meta,极大减少资源消耗。
- 如需进一步优化(如批量处理时分批执行以防超时),可再细化。
- 如有自定义图片数量或路径,请自行调整 mt_rand(1, 62) 和图片目录。
评论抢沙发