既存のサイトをCMS化する際にHTMLで書かれた過去記事などをインポートする場面ってありますよね。
件数が二桁くらいなら気合で乗り切れるかも知れませんが、三桁、四桁になると現実的ではありません、、、
そこでPHPを使ってHTMLをWordPressにインポートする方法を紹介します。
HTMLの抜き出し
①HTMLの取得
1 2 3 | $html = file_get_contents('【URL】'); |
file_get_contents関数を使うことで、$htmlに指定したURLのHTMLが文字列として入ります。
②特定のHTMLを抜き出し
「preg_match関数」と「preg_match_all関数」を用途に応じて使い分けます。
「preg_match関数」はマッチするものを一つ持ってくる。
「preg_match_all関数」はマッチしたものすべてを持ってくる。
第一引数 : 正規表現を記述する。
第二引数 : パターンマッチの対象となる文字列を指定する。
第三引数 : 配列変数を渡す。パターンマッチに成功した場合はその配列変数に値が格納される。
配列変数は$変数[0]に正規表現の全体が格納され、$変数[1]に「()」でマッチした部分が格納されます。
「()」の数に応じて$変数[2]$変数[3]と追加されていきます。
正規表現の注意点
第一引数にある「正規表現」とは、ある条件にマッチするいつくかの文字列を一つのパターンだけで表す方法です。
リテラル記号
PHPとしての文字列なので「’」か「”」で囲む必要があります。エスケープする機会が少なくなるように選択します。
抜き出す対象のHTMLが属性を「”」で囲んでいるなら「’」を選択するとコードが読みやすくなります。
1 2 3 4 5 | //リテラル記号が「"」 "<div class=\"txt\"></div>" //リテラル記号が「'」 '<div class="txt"></div>' |
デリミタ
PHPのpreg系の関数では、パターン文字列自体を何かで挟む必要があります。「/」で囲むことが一般的ですが、パターン内に閉じタグがあるとエスケープする必要が出てきます。PHPでは、両端が同じ文字で挟まれていればデリミタとして認められるので「@」で書くとコードが読みやすくなります。
1 2 3 4 5 | //デリミタが「/」 '/<div class="txt"><\/div>/' //デリミタが「@」 '@<div class="txt"></div>@' |
オプション
デリミタの後ろに記述することで設定できます。
改行混じりの複数行をマッチさせたいときには「sオプション」を使います。
ピリオドが改行にもマッチするようになるので、「.*」で改行またぎにマッチします。
その他オプションはPHP マニュアルをご覧ください。
最短マッチの指定
「?」を使うことで、一番近いものにマッチするようになります。
1 2 | '@<div class="txt">(.*?)</div>@s' |
この正規表現では「<div class=”txt”>」から最初に出てきた「</div>」にマッチして止まってくれます。
HTML抜き出しの例
1 2 3 4 5 6 7 8 9 10 11 12 13 | <h1>タイトル</h1> <div class="name">会社名</div> <div class="txt"> テキスト1 </div> <div class="txt"> テキスト2 </div> <div class="txt"> テキスト3 </div> |
注意点を踏まえて上記の「タイトル」「会社名」「テキスト1~3」を抜き出すには
1 2 3 4 | preg_match('@<h1>(.*?)</h1>@s', $html, $ttl);//タイトル preg_match('@<div class="name">(.*?)</div>@s', $html, $company_name);//会社名 preg_match_all('@<div class="txt">(.*?)</div>@s', $html, $txt);//テキスト1~3 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | //$ttl Array ( [0] => <h1>タイトル</h1> [1] => タイトル ) //$company_name Array ( [0] => <div class="name"> 会社名 </div> [1] => 会社名 ) //$txt Array ( [0] => Array ( [0] => <div class="txt"> テキスト1 </div> [1] => <div class="txt"> テキスト2 </div> [2] => <div class="txt"> テキスト3 </div> ) [1] => Array ( [0] => テキスト1 [1] => テキスト2 [2] => テキスト3 ) ) |
このような配列で取得する事ができます。
しかしこのままでは余分な空白や改行を含んだままですので「preg_replace」を使って取り除きます。
1 2 3 | $txt = preg_replace('@\n|\r\n|\r|( | )@', '', $txt[1]); |
1 2 3 4 5 6 7 8 9 10 | //$txt Array ( [0] => テキスト1 [1] => テキスト2 [2] => テキスト3 ) |
詳しくはPHP正規表現の使い方まとめをご覧ください。
WordPressへのインポート
まずはWordPressの関数を使う準備をします。
1 2 3 | require_once ('【WordPressのルートディレクトリ】/wp-load.php'); |
カスタム投稿に新規追加
カスタム投稿の新規追加に必要なコードは以下のようになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ... // 投稿日時 $format = '2021-08-11 00:00:00 +' . $i . ' min'; $date = date('Y-m-d H:i:s', strtotime($format)); //記事データを作成 $post_value = array( 'post_title' => $title[1], // 投稿のタイトル 'post_status' => 'publish', // 公開ステータス 'post_type' => 'news', // 投稿タイプ 'post_date' => $date // 投稿の作成日時 ); $insert_id = wp_insert_post($post_value); if ($insert_id) { update_post_meta($insert_id, '【カスタムフィールド名】', $company_name[1]); } foreach ($txt[1] as $value) { add_post_meta($insert_id, '【カスタムフィールド名】', $value); } $i++; ... |
カスタムフィールドに抜き出したHTMLを設定する
単体のカスタムフィールドは「update_post_meta」を使って値を設定します。
1 2 3 | update_post_meta($insert_id, '【カスタムフィールド名】', $company_name[1]); |
繰り返しカスタムフィールドの場合は「add_post_meta」を使います。
1 2 3 4 5 | foreach ($txt[1] as $value) { add_post_meta($insert_id, '【カスタムフィールド名】', $value); } |
投稿日時をずらす
「$date」で投稿日時を記事ごとに1分ずつずらしています。投稿日時が重複してしまうと、記事を一覧表示した時の並び順やページネーションがおかしくなることがあるためです。
$formatの「min」の部分を変更する事で時間や秒単位でずらせます。
1 2 3 4 | $format = '2021-08-11 00:00:00 +' . $i . ' min'; $date = date('Y-m-d H:i:s', strtotime($format)); |
まとめ
今回はHTMLを取得して、その情報をWordPressで新規記事作成という形式でインポートする手順を紹介しました。
インポートの前に少ない件数でテストをしたり、WordPressのバックアップを取っておくと予期せぬエラーに対応できると思います。
HTML構造が複雑な場合は二回に分けて「preg_match」「preg_match_all」を使うと意外と簡単に抜き出せる時がありました。
また抜き出したHTML情報を、既存の投稿に更新する形式でインポートする事も可能です。
この手順につきましては下記BRISKの過去記事に詳しく書かれているので、こちらをぜひ読んでみてください。
CSVインポート処理の決定版