Blog

WordPressサイトをwgetで保存する際にページングがある記事で失敗するときのworkaround

こんにちは、WEBサービス開発グループの伊達です。今日はちょっとした小ネタです。

先日、WordPressで運用しているサイトをクローズするのでローカルで閲覧できるようにダウンロードしてほしいという依頼がありました。

この際に、ページングのある記事をうまく保存できない問題があったので、ちょっとした方法で回避しましたという話をします。

wgetでダウンロード

過去にもクローズするサイトを丸ごとダウンロードしたいという依頼を受けたことがあり、そんな時にはwgetを使って、

としていました。それぞれのオプションの意味は以下の通りです。

-m で再帰的にダウンロードし、-k-pでローカルで閲覧が完結できるようにします。-Eで、HTML文書は必ず.htmlという拡張子で保存するようにします。また、コマンドはLinux上で実行しますが閲覧はWindowsですので、Windowsで使用できないファイル名を避けるために --restrict-file-name=windows を付けます。

問題発覚

今回も同じようにダウンロードして、zipで固めたファイルを渡したところ、

「ダウンロードできていない記事があります。ページングのある記事があったりなかったりします」

との連絡が。

よくよく確認してみますと、ページングのURL仕様が原因だとわかりました。

  • 該当の記事のURL http://example.org/blog/2011/01/1.html
  • 該当の記事の2ページ目のURL http://example.org/blog/2011/01/1.html/2

わかりますでしょうか?

問題の詳細

wgetが上の記事をクローリングしますと、

  1. http://example.org/blog/2011/01/1.htmlをクロールしてリンクを探す
  2. 2ページ目であるhttp://example.org/blog/2011/01/1.html/2をクロールする
  3. http://example.org/blog/2011/01/1.html/2example.org/blog/2011/01/1.html/2.htmlとして保存する
    • そのために example.org/blog/2011/01/1.html というディレクトリを作成する
  4. example.org/blog/2011/01/1.htmlというディレクトリがすでにあるため、http://example.org/blog/2011/01/1.htmlexample.org/blog/2011/01/1.htmlとして保存できない……

という挙動になります(逆にディレクトリの作成できないケースもあり)。

解決案を考える

さて、この問題をどうやって解決するとよいでしょうか。私はwgetのmanpageを眺めながら以下のような案を考えました。

  • wgetのオプションにHTMLファイルの拡張子を.htmlではなく、.htmにするものはないか
    • (これができれば、ディレクトリは1.html、記事本体は1.htmと別の名前になります)
    • -E.html固定だった
  • wgetのオプションにファイルの保存時にコマンド実行を挟むようなコールバックがないか
    • → さすがにない
  • 1度wgetした後に該当の記事のディレクトリ名を変更し、影響を受けるHTMLをsedを使って修正、その後にもう一度wget
    • → サイト全体のダウンロードに1時間以上かかるため、試行錯誤は避けたい

簡単に解決できる方法はなさそうです。

いえ、本当にそうでしょうか。
最初にあたりを付けていた-EはHTMLファイルの拡張子を .htmlに強制するオプションです。
コマンドラインから拡張子を指定する方法はありませんが、ソースコードにはその処理が書かれているはずです。
処理を少し変更すれば、拡張子を.htmにしてファイル名とディレクトリ名の重複を避けられるのでは。

アドホックなworkaround

ということで、

  • -Eオプション指定時の挙動を修正して、HTMLファイルは .htm で保存されるようにする

ことができないか試してみることにしました。

コードを調べる

まずはソースコードをダウンロードして展開します。

-Eオプションの挙動を素直に実装しているなら.htmlという文字列がソースコード上に登場するだろうとあたりを付けてgrepします。

様々なファイルでマッチしますが、ensure_extensionという関数名と文字列".html"の存在から、http.cの3774行目がどうも怪しい!

前後のコードを見てみるとコメンドで-Eオプションについて言及しており当たりのようです(実際には、もう少しあちこち調べましたが……)。

修正してビルド

http.cを上記の通りに修正してからビルドします。

これで、/home/date/wget/binに改造したwgetコマンドがインストールされます。

結果

改造したwgetでダウンロードし直したところ、懸案の記事は以下の通りにダウンロードされるようなりました。

  • 該当の記事 http://example.org/blog/2011/01/1.htmlexample.org/blog/2011/01/1.html.htm
  • 該当の記事の2ページ目 http://example.org/blog/2011/01/1.html/2example.org/blog/2011/01/1.html/2.htm

拡張子が重複しているのが気になりますが、リンクはちゃんとされていますし、ローカルで閲覧ができるという要件は満たしていますから問題ないでしょう。

結論

ソースコードはエンジニアの強い味方です。