乐于分享
好东西不私藏

wordpress无需插件批量优化 WordPress 图片 Alt 和 Title

wordpress无需插件批量优化 WordPress 图片 Alt 和 Title

想必大家在维护网站的时候都会遇到一个问题、就是很多网站的历史图片都没有默认的”alt”、”title”信息、导致网站在图片seo这方面很差。

手动更改的话图片太多、更改起来工作量太大、而市面上的大部分插件都不太满足要求、并且很多是收费的。

今天给大家分享一串代码来解决这个问题。

这段代码能做什么?

根据图片所属文章/产品的标题,自动填充图片的 alt 和 title。

核心能力包括:

– 自动识别图片所属内容(文章 / 页面 / 产品) 

– 支持 WooCommerce(商品特色图 + 相册图) 

– 分批批量处理,不会卡死服务器 

– 支持“只改空值”或“强制覆盖” 

使用方法:(代码注释有说明、可以根据需求开关)

  1. 把代码放进 functions.php、或者用代码片段插件插入代码

  2. 打开浏览器访问:/wp-admin/?run_image_meta_sync=1

  3. 在页面手动进行下一步操作

  4. 代码执行完后记得删除之前添加的代码。

注意事项:

在执行脚本前请先备份数据库以及程序文件、操作不会影响程序文件、但是一起备份、避免出现不可知问题无法恢复。

代码如下:

add_action('admin_init''my_bulk_update_image_alt_title_from_parent_content');functionmy_bulk_update_image_alt_title_from_parent_content() {    // 访问后台并带上这个参数才执行:    // /wp-admin/?run_image_meta_sync=1    if (!is_admin() || !current_user_can('manage_options') || !isset($_GET['run_image_meta_sync'])) {        return;    }    // ===== 配置区 =====    $overwrite_existing_alt   = false;   // true = 强制覆盖 alt;false = 只改空 alt    $overwrite_existing_title = true;    // true = 强制覆盖 title;false = 只改空 title    $batch_size               = 50;      // 每批处理50张图片,更稳,避免超时    $dry_run                  = false;   // true = 只预览不写入;false = 实际写入    // =================    // 防止超时    @set_time_limit(0);    @ignore_user_abort(true);    $paged = isset($_GET['img_page']) ? max(1intval($_GET['img_page'])) : 1;    $args = array(        'post_type'      => 'attachment',        'post_status'    => 'inherit',        'post_mime_type' => 'image',        'posts_per_page' => $batch_size,        'paged'          => $paged,        'orderby'        => 'ID',        'order'          => 'ASC',        'fields'         => 'ids',    );    $query = new WP_Query($args);    $processed = 0;    $updated   = 0;    $skipped   = 0;    // 输出样式和头部信息    echo '<div class="wrap"><h1>Image Alt/Title Sync</h1>';    if ($dry_run) {        echo '<div style="background:#fff3cd; border-left:4px solid #ffc107; padding:10px; margin:10px 0;">';        echo '<strong>⚠️ DRY RUN MODE (预览模式)</strong> - 没有实际写入数据库,只是预览将要进行的更改。<br>';        echo '要实际写入,请将代码中的 $dry_run 改为 false。</div>';    }    echo '<div style="background:#f1f1f1; padding:10px; margin:10px 0; font-family:monospace;">';    echo '<strong>Batch:</strong> ' . intval($paged) . ' / ' . intval($query->max_num_pages) . '<br>';    echo '<strong>Batch Size:</strong> ' . intval($batch_size) . ' images<br>';    echo '<strong>Overwrite Alt:</strong> ' . ($overwrite_existing_alt ? 'Yes' : 'No (only empty)') . '<br>';    echo '<strong>Overwrite Title:</strong> ' . ($overwrite_existing_title ? 'Yes' : 'No (only empty)') . '<br>';    echo '</div>';    if (!empty($query->posts)) {        foreach ($query->posts as $attachment_id) {            $processed++;            $target_title = my_get_best_title_for_attachment($attachment_id);            if ($target_title === '') {                $skipped++;                continue;            }            $target_title = trim(wp_strip_all_tags($target_title));            if ($target_title === '') {                $skipped++;                continue;            }            $did_update = false;            $changes = array();            // 更新 alt            $current_alt = get_post_meta($attachment_id'_wp_attachment_image_alt'true);            $alt_was_empty = trim((string$current_alt) === '';            if ($overwrite_existing_alt || $alt_was_empty) {                if (!$dry_run) {                    update_post_meta($attachment_id'_wp_attachment_image_alt'$target_title);                }                $did_update = true;                if ($alt_was_empty) {                    $changes[] = 'alt (was empty) → ' . $target_title;                } else {                    $changes[] = 'alt (overwritten) → ' . $target_title;                }            }            // 更新 title(附件 post_title)            $attachment_post = get_post($attachment_id);            $current_title   = $attachment_post ? $attachment_post->post_title : '';            $title_was_empty = trim((string$current_title) === '';            if ($overwrite_existing_title || $title_was_empty) {                if (!$dry_run) {                    wp_update_post(array(                        'ID'         => $attachment_id,                        'post_title' => $target_title,                    ));                }                $did_update = true;                if ($title_was_empty) {                    $changes[] = 'title (was empty) → ' . $target_title;                } else {                    $changes[] = 'title (overwritten) → ' . $target_title;                }            }            if ($did_update) {                $updated++;                if ($dry_run) {                    // 预览模式下输出详细信息                    echo '<div style="font-size:12px; border-bottom:1px solid #eee; padding:2px 0;">';                    echo 'ID: ' . intval($attachment_id) . ' → ' . esc_html($target_title);                    if (!empty($changes)) {                        echo ' (' . esc_html(implode(', '$changes)) . ')';                    }                    echo '</div>';                    flush();                }            } else {                $skipped++;            }        }    }    // 输出结果统计    echo '<div style="background:#d4edda; border-left:4px solid #28a745; padding:10px; margin:20px 0 10px 0;">';    echo '<strong>📊 本批统计</strong><br>';    echo 'Processed: ' . intval($processed) . '<br>';    echo 'Updated: ' . intval($updated) . '<br>';    echo 'Skipped: ' . intval($skipped) . '<br>';    echo '</div>';    // 下一页继续跑    if ($paged < $query->max_num_pages) {        $next_page_url = add_query_arg(array(            'run_image_meta_sync' => 1,            'img_page'            => $paged + 1,        ), admin_url());        echo '<p><a class="button button-primary" href="' . esc_url($next_page_url) . '">▶ 继续下一批 (' . intval($paged + 1) . ' / ' . intval($query->max_num_pages) . ')</a></p>';        echo '<p><small>提示:点击按钮继续处理下一批图片。建议每批完成后检查是否有错误。</small></p>';    } else {        echo '<div style="background:#cce5ff; border-left:4px solid #004085; padding:10px; margin:20px 0 10px 0;">';        echo '<strong>✅ 全部完成!</strong><br>';        echo '所有批次已处理完毕。<br>';        echo '如需重新运行,请再次访问此页面。</div>';        echo '<p><a class="button button-secondary" href="' . esc_url(admin_url()) . '">返回后台首页</a></p>';    }    echo '</div>';    exit;}/** * 为附件找最合适的标题来源: * 1. 附件父级 post_parent * 2. WooCommerce 产品特色图 * 3. WooCommerce 产品相册图 * 4. 普通文章/页面特色图 */functionmy_get_best_title_for_attachment($attachment_id{    $attachment_id = intval($attachment_id);    if (!$attachment_id) {        return '';    }    // 1) 优先用附件父级    $attachment = get_post($attachment_id);    if ($attachment && !empty($attachment->post_parent)) {        $parent_id = intval($attachment->post_parent);        $parent    = get_post($parent_id);        if ($parent && in_array($parent->post_type, array('product''post''page'), true)) {            $title = get_the_title($parent_id);            if (!empty($title)) {                return $title;            }        }    }    global $wpdb;    // 2) WooCommerce 产品特色图    $product_featured_id = $wpdb->get_var($wpdb->prepare("        SELECT p.ID        FROM {$wpdb->posts} p        INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id        WHERE p.post_type = 'product'          AND p.post_status IN ('publish', 'private', 'draft')          AND pm.meta_key = '_thumbnail_id'          AND pm.meta_value = %d        LIMIT 1    ", $attachment_id));    if ($product_featured_id) {        $title = get_the_title($product_featured_id);        if (!empty($title)) {            return $title;        }    }    // 3) WooCommerce 产品相册图    $gallery_product_id = $wpdb->get_var($wpdb->prepare("        SELECT p.ID        FROM {$wpdb->posts} p        INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id        WHERE p.post_type = 'product'          AND p.post_status IN ('publish', 'private', 'draft')          AND pm.meta_key = '_product_image_gallery'          AND CONCAT(',', pm.meta_value, ',') LIKE CONCAT('%%,', %d, ',%%')        LIMIT 1    ", $attachment_id));    if ($gallery_product_id) {        $title = get_the_title($gallery_product_id);        if (!empty($title)) {            return $title;        }    }    // 4) 普通文章/页面/产品特色图    $featured_post_id = $wpdb->get_var($wpdb->prepare("        SELECT p.ID        FROM {$wpdb->posts} p        INNER JOIN {$wpdb->postmeta} pm ON p.ID = pm.post_id        WHERE p.post_type IN ('post', 'page', 'product')          AND p.post_status IN ('publish', 'private', 'draft')          AND pm.meta_key = '_thumbnail_id'          AND pm.meta_value = %d        LIMIT 1    ", $attachment_id));    if ($featured_post_id) {        $title = get_the_title($featured_post_id);        if (!empty($title)) {            return $title;        }    }    return '';}

加入代码后访问下面的地址:

你的域名/wp-admin/?run_image_meta_sync=1

代码是直接更改的数据库的、所以更改完成后删除添加的代码即可、为了安全也建议删除。