最後更新:2026/10/15
寫了八年的痞客邦部落格,六百篇文章匯進 WordPress,看起來一切正常,直到某天打開舊文章,圖片全變成破圖。原因很簡單:匯入的只有文字,文章裡的圖片網址還是 pimg.tw 開頭,圖片檔案一直放在舊平台的主機上。舊平台限制外連、改網址、或哪天關站,你的文章就只剩文字。
〈WordPress 網站搬家〉那篇講的是整個 WordPress 搬主機,圖片會跟著搬;這篇處理的是從別的平台搬過來、圖片沒跟來的情況。做法是一段程式碼,在後台「工具」多一個「抓回外站圖片」頁面:先預覽每篇文章有幾張外站圖片,確認後一鍵把它們下載進自己的媒體庫,並把文章裡的網址換成自己的。
不想自己改?把這篇交給 AI
把這篇的網址(或全文)連同下面這段話貼給 AI:
我的網站是 WordPress。我從別的平台搬過來,文章裡的圖片還連著舊平台的網址,我想照下面這篇文章把它們抓回自己的媒體庫。
請先問我:舊平台是哪一個、大約有幾篇文章、主機空間還剩多少、有沒有先備份資料庫。
問清楚之後,再一步一步告訴我:要用哪一段程式碼、貼在哪裡、怎麼先預覽再執行,以及跑完怎麼確認。
如果文章的做法不適合我的網站,請直接告訴我原因和替代做法。
文章:(貼上這篇的網址,或整篇內容)
改之前先備份,密碼不要貼給 AI。
完整程式碼
// 第 85 篇:把文章裡的外站圖片抓回自己的媒體庫
// 處理一篇文章:找出不是自己網站的 <img>,下載進媒體庫,把網址換掉
function mimi_localize_images($post_id, $dry_run = true) {
require_once ABSPATH . 'wp-admin/includes/media.php';
require_once ABSPATH . 'wp-admin/includes/file.php';
require_once ABSPATH . 'wp-admin/includes/image.php';
$post = get_post($post_id);
$content = $post->post_content;
$home = wp_parse_url(home_url(), PHP_URL_HOST);
$result = ['post' => $post_id, 'found' => 0, 'replaced' => 0, 'failed' => []];
preg_match_all('/<img[^>]+src=["\']([^"\']+)["\']/i', $content, $m);
foreach (array_unique($m[1]) as $src) {
$host = wp_parse_url($src, PHP_URL_HOST);
if (!$host || $host === $home) {
continue; // 自己的圖,跳過
}
$result['found']++;
if ($dry_run) {
continue;
}
$new = media_sideload_image($src, $post_id, null, 'src'); // 下載、建附件、回傳新網址
if (is_wp_error($new)) {
$result['failed'][] = $src . ':' . $new->get_error_message();
continue;
}
$content = str_replace($src, $new, $content);
$result['replaced']++;
}
if (!$dry_run && $result['replaced']) {
wp_update_post(['ID' => $post_id, 'post_content' => $content]);
}
return $result;
}
// 後台工具:工具 > 抓回外站圖片。先「預覽」看有幾張,再「開始」
add_action('admin_menu', function () {
add_management_page('抓回外站圖片', '抓回外站圖片', 'manage_options', 'mimi-localize', function () {
$go = !empty($_POST['go']) && check_admin_referer('mimi_localize');
$ids = get_posts(['post_type' => ['post', 'page'], 'post_status' => 'any', 'numberposts' => -1, 'fields' => 'ids']);
echo '<div class="wrap"><h1>抓回外站圖片</h1>';
$total = ['found' => 0, 'replaced' => 0, 'failed' => []];
foreach ($ids as $id) {
$r = mimi_localize_images($id, !$go);
if ($r['found']) {
echo '<p>' . esc_html(get_the_title($id)) . ':外站圖片 ' . $r['found'] . ' 張' . ($go ? ',抓回 ' . $r['replaced'] . ' 張' : '') . '</p>';
$total['found'] += $r['found'];
$total['replaced'] += $r['replaced'];
$total['failed'] = array_merge($total['failed'], $r['failed']);
}
}
echo '<p><strong>' . ($go ? '完成:抓回 ' . $total['replaced'] . ' 張' : '共 ' . $total['found'] . ' 張外站圖片(還沒抓)') . '</strong></p>';
foreach ($total['failed'] as $f) {
echo '<p style="color:#b32d2e">失敗:' . esc_html($f) . '</p>';
}
echo '<form method="post">' . wp_nonce_field('mimi_localize', '_wpnonce', true, false) . '<button class="button button-primary" name="go" value="1">開始抓回(先備份資料庫)</button></form></div>';
});
});
程式碼放在 Code Snippets 這類外掛或子主題,放法和備份方式見〈WooCommerce 結帳頁改成台灣習慣〉。
兩段各做了什麼
第一段是處理一篇文章的函式。它用正規表示式找出內文所有 <img> 的網址,網域和自己網站一樣的跳過,其他的算成外站圖片。「預覽」模式只數有幾張;「執行」模式對每一張呼叫 WordPress 內建的 media_sideload_image:下載檔案、放進上傳資料夾、建一筆媒體庫的附件、產生各種尺寸的縮圖,然後回傳新的網址。程式再把內文裡的舊網址換成新網址,全部換完才存回文章。下載失敗的圖片會記下原因,內文裡那一張保持原樣,不會變成空白。
第二段在後台「工具」選單下加一頁「抓回外站圖片」。打開頁面就是預覽:列出每一篇有外站圖片的文章和張數,最後一行是總數。按「開始抓回」才真的執行,執行完同一頁顯示每篇抓回幾張、哪幾張失敗。只有管理員看得到這一頁。
測試結果
我們在本機測試站建一篇「搬家來的文章」,放三張圖:兩張連到 WordPress.org 的圖(一張 PNG 的 Logo、一張 SVG 的表情符號),一張是自己網站的:
- 預覽顯示「外站圖片 2 張」,自己網站那張沒有被算進去。
- 執行後顯示「抓回 1 張」和一行失敗:SVG 那張的錯誤是「無效的圖片網址」,因為 WordPress 預設不允許上傳 SVG。
- 重新打開文章,PNG 的網址已經變成自己網站
wp-content/uploads/底下的檔案,SVG 那張還是原本的網址,自己的那張沒動。
跑之前要知道的幾件事
數量多的時候分批跑。六百篇文章、三千張圖一次抓,網頁可能等到逾時。這段程式碼為了簡單是一次處理全部,文章多的網站可以把 numberposts 改成 50,跑完再跑,或是請懂的人改成用排程分批。
主機空間要夠。圖片抓回來就是放在自己的主機上,三千張圖加上縮圖可能是幾 GB,先看主機還剩多少空間。不想讓每張圖產生十幾個縮圖,可以先看〈WordPress 停止產生多餘縮圖〉。
舊平台擋下載。有些平台會擋沒有來源網頁的圖片請求(防盜連),下載會失敗。失敗的清單會列在頁面上,這些圖只能手動存下來再上傳。另外,只有確定是你自己上傳到舊平台的圖片才抓;別人網站的圖片本來就不該出現在你的文章裡。
跑完記得備份。程式會改文章內文,跑之前備份一次資料庫,跑完確認沒問題再做一次完整備份,備份方法在〈WordPress 網站上線前的檢查清單〉。
圖片放在自己的主機,文章才真的是你的
搬家的意義是把內容放在自己手上,圖片留在舊平台等於只搬了一半。抓回來之後,網站的速度、縮圖、WebP 轉換都能自己控制,舊平台怎麼變都不影響你。這也是〈IG 帳號不是你的資產〉那篇講的:平台上的東西隨時會變,自己網站上的才算數。
如果你正打算從痞客邦、Blogger 或其他平台搬到自己的網站,想一次把文章、圖片、網址轉址都處理好,MIMI 專做客製化網頁設計,可以替你規劃搬家流程。MIMI 提供台灣網頁設計服務,全台灣的創作者都可以用電話、Email 直接和設計師討論;費用可以先看首頁的製作費用參考,歡迎聯絡 MIMI。
