WordPressの投稿画面を使わないで画像を投稿へ紐づけ

1つ2つ記事を投稿するときは、WordPressの新規投稿の画面でなんの問題もないと思うんですが、
例えば、3400件ほど記事を作成して、その1つずつに30枚ほど画像を貼り付ける(102,000枚)のをバイト代出すからと言われても、手でやりたいと思いますか?
 
こういうときに、ハイっと言ってすぐ画面に向かって入力し続ける人の方がいまどきは稼げるかもしれませんが(1件の投稿と画像紐づけに1分かかったとして、1時間で60件、全部処理するのに、約57時間、時給1,000円で 57,000円か。こんなこと書いてないで、すぐやってもいいかも)、2時間くらいでめげる人のためにツールを使ってなるべく楽チンに画像を紐づける方法をまとめてみたいと思います。

 
大前提として、DBを直接いじれる(SQLが実行できる)必要があります。phpAdminみたいなツールでいいんじゃないでしょうか。(私は大人の都合で、phpPgAdminを使ってますが。多量にSQLを流すときは、psqlです)
あと、Rubyなんかが手元で動くといいですね。マストではないですけど。
 
それでは、素晴らしく簡潔に書きます。(結局あとで自分が見るためのまとめということです)
 

  1. 投稿記事の準備(流し込み)
    wp_postsテーブルへ insert文で流し込んじゃってください。(↓サンプル)

    insert into wp_posts (
    post_author,post_date,post_date_gmt,
    post_content,post_title,post_excerpt,post_status,
    comment_status,ping_status,post_password,post_name,
    to_ping,pinged,post_modified,post_modified_gmt,
    post_content_filtered,post_parent,guid,menu_order,
    post_type,post_mime_type,comment_count) values (
    2, '2010-05-18 09:30:00', '2010-05-18 00:30:00','本文',
    'タイトル','','publish','open','open','','post_name',
    '','','2010-05-18 09:30:00', '2010-05-18 00:30:00',
    '','0','http://test.jp/items/','0','post','','0');
    
  2. 投稿記事 guidの修正
    上のままだと、guidが空っぽなので、wp_postsテーブルで ”ID”を確認して updateしておきます。(きっと一発で、insertしたときの autoincキーを insert文の中でセットするようなことが SQLでできるんじゃないかな? できないのかな?)

    update wp_posts
    set guid = 'http://test.jp/items/1234'
    where "ID" = 1234;
    

    上で insert文を流した直後だと、autoincキーは連続しているので、自動的に update文は作れて簡単ですね。

  3. アタッチする画像の準備
    WordPressの画像には、サムネイル、中サイズ、大サイズ、フルサイズの4種類があります。
    新規投稿でメディアを追加すると WordPressが勝手に作ってくれるので楽ちんですが、今回はそれができないので自分で作ります。
    私が使っているのは、Ralpha です。ファイル数が数千、数万単位になるとメモリエラーで落ちるのが玉に傷ですが(エクスプローラがタコなせいで落ちている気もするので、Ralphaが悪いわけではないかも)、そんなヘビーなことはめったにないので、ありがたく使わせていただいてます。
    Ralphaを使って、サムネイルサイズ(例として、100×75)、中サイズ(同じく、180×135)、大サイズ(800×600)を作ります。使い方は、Ralphaのヘルプを見てください。
    リサイズとともにリネームもできますので、元の画像を残しておいて、別フォルダに code001-100×75.jpg みたいなファイルを作成しておいてください。命名規則は WordPress標準です。

  4. 画像サイズによるリネーム・ツール
    画像ファイルがたくさんあって、サイズがまちまちだと Ralphaでいちいちリネームするのが面倒なので、こんなツールでリネームしてます。

    def get_imgsize(path, type = :auto)
      if type == :auto
        type = File.extname(path)[1..-1].downcase.to_sym
        type = :jpeg if type == :jpg
      end
      File.open(path, "rb") do |f|
        case type
        when :jpeg
          while true
            break unless f.read(1) == "\xff"
            case f.read(1)
            when "\xc0", "\xc2"
              f.seek(3, IO::SEEK_CUR)
              return f.read(4).unpack("n2").reverse
            when "\xd8", "\xd9"
            when "\x00"
              break
            else
              f.seek(f.read(2).unpack("n")[0] - 2, IO::SEEK_CUR)
            end
          end
          raise RuntimeError, "analysis failed"
        when :png
          if f.read(8) == "\x89PNG\r\n\x1a\n"
            f.seek(8, IO::SEEK_CUR)
            return f.read(8).unpack("N2")
          else
            raise RuntimeError, "analysis failed"
          end
        when :gif
          if f.read(3) == "GIF"
            f.seek(3, IO::SEEK_CUR)
            return f.read(4).unpack("v2")
          else
            raise RuntimeError, "analysis failed"
          end
        else
          raise ArgumentError, "#{type} is unsupported"
        end
      end
    end
    
    for y in [2009, 2010]
      for m in [1,2,3,4,5,6,7,8,9,10,11,12]
        t = "%02d" % m
        d = "C:/Work/test/#{y}/#{t}/resize/*.jpg"
        Dir::glob(d).each {|f|
          width, height = get_imgsize(f)
          a = f.split(/.jpg/)
          s = "#{a[0]}-#{width}x#{height}.jpg"
          File::rename(f, s)
          puts s
        }
      end
    end
    

    get_imgsize()はどこかで拾ってきました。ありがとう。

  5. 画像ファイルのコピー・ツール
    サーバがネットワーク上にある環境だとコピーもこんなのでできます。もちろん通常は FTPなんかでやるんですよね。

    require 'ftools'
    
    for y in [2009, 2010]
      for m in [1,2,3,4,5,6,7,8,9,10,11,12]
        t = "%02d" % m
        d = "C:/Work/test/#{y}/#{t}/resize/*.jpg"
        Dir::glob(d).each {|f|
          dd = "//192.168.1.200/wordpress/wp-content/uploads/#{y}/#{t}/#{File.basename(f)}"
          File.copy(f, dd, true)
        }
      end
    end
    
  6. カテゴリの登録
    wp_postsテーブルへ insertしただけだと、カテゴリが未分類のままなので、wp_term_relationshipsテーブルにも insertしておきます。(↓サンプル)

    insert into wp_term_relationships
    values (1128,8,0);
    
  7. 画像の登録(1)
    さて、ここからが本題です。画像をサーバのフォルダに移しただけだと WordPressからは見えてないので、投稿記事と紐づける(アタッチする)必要があります。
    こんな感じで、wp_postsテーブルへ insertします。(↓サンプル)

    insert into wp_posts(
    post_author,post_date,post_date_gmt,
    post_content,post_title,post_excerpt,
    post_status,comment_status,ping_status,
    post_password,post_name,to_ping,pinged,
    post_modified,post_modified_gmt,
    post_content_filtered,post_parent,guid,
    menu_order,post_type,post_mime_type,
    comment_count) values(
    2,'2010-05-18 09:00:00','2010-05-18 00:00:00',
    '','file_1','','inherit','open','open','','file_1',
    '','','2010-05-18 09:00:00','2010-05-18 00:00:00','',
    1289,
    'http://test.jp/wp-content/uploads/2008/12/file_1.jpg',
    0,'attachment','image/jpeg',0);
    

    “file_1.jpg”というのがフルサイズの画像ファイル名です。post_contentは空っぽでいいですが、post_titleとpost_nameにファイル名(拡張子なし)を入れておきます。
    post_parentのところに紐づける記事IDを入れるのがキモですね。

  8. 画像の登録(2)
    上で insertしたレコードの autoincキーで今度は wp_postmetaテーブルにレコードを作ります。

    insert into wp_postmeta
    (post_id,meta_key,meta_value)
    values(15873,'_wp_attached_file',
    '2008/12/file_1.jpg');
    

    投稿記事のID(上の例では 1289)ではなくて、画像自体のID(上の insert文を実行して挿入されたレコードの”ID”)を post_idにするところがミソですね。
    ここではファイル名だけの insertなので、もう1つあります。

  9. 画像の登録(3)
    同じ autoincキーでもう1レコード、wp_postmetaテーブルに挿入します。

    insert into wp_postmeta
    (post_id,meta_key,meta_value)
    values(
    15873,'_wp_attachment_metadata',
    E'a:6:{s:5:"width";s:3:"800";s:6:"height";s:3:"600";s:14:"hwstring_small";s:0:"";s:4:"file";s:18:"2008/12/file_1.jpg";s:5:"sizes";a:3:{s:9:"thumbnail";a:3:{s:4:"file";s:17:"file_1-100x75.jpg";s:5:"width";s:3:"100";s:6:"height";s:2:"75";}s:6:"medium";a:3:{s:4:"file";s:18:"file_1-171x128.jpg";s:5:"width";s:3:"171";s:6:"height";s:2:"128";}s:14:"post-thumbnail";a:3:{s:4:"file";s:17:"file_1-100x75.jpg";s:5:"width";s:3:"100";s:6:"height";s:2:"75";}}s:10:"image_meta";a:10:{s:8:"aperture";s:0:"";s:6:"credit";s:0:"";s:6:"camera";s:0:"";s:7:"caption";s:0:"";s:17:"created_timestamp";s:0:"";s:9:"copyright";s:0:"";s:12:"focal_length";s:0:"";s:3:"iso";s:0:"";s:13:"shutter_speed";s:0:"";s:5:"title";s:0:"";}}');
    

    カメラパラメータ系のいらないところは空白にしてあります。
    これでOKです。どうです、面倒臭いでしょ。
    この最後のレコードはもしかしたら、画像ファイルの縮小サイズを自動的に再登録してくれるプラグイン(Regenerate Thumbnails)が作ってくれるかもしれないので、そっちでやった方が楽かもしれません。