
現在は改善されていますが,みんカラのディレクトリ構成が非常に使いづらいということを
2 年ほど前に書きました.現在のトップページ (URL) は
http://minkara.carview.co.jp/userid/124081/ ですが,当時は
http://carlife.carview.co.jp/User.asp?UserID=124081 で,それぞれの記事はこれに似た URL である
http://carlife.carview.co.jp/User.asp?UserDiaryID=8601430 のような形式でした.すなわち,124081 たる私が書いた記事がどこにあるか,URL からではまったく判らないのです.
このため,
http://carlife.carview.co.jp/User.asp?UserID=124081 から再帰的にディレクトリをたどって自分の記事だけを全部読み込むことが非常に困難でした.
しかしながら 2006 年 10 月ごろにこれが改善され (私がこのことを書いたからではないと思いますが :-) 同様の意見多数だったのでしょう),現在はトップページが
http://minkara.carview.co.jp/userid/124081/ のような通常の URL に変わり,個々の記事は
http://minkara.carview.co.jp/userid/124081/blog/1876317/ といった,ユーザ ID が含まれるパーマネントリンクを持つことになりました.全記事を最新から古い方へたどるには
http://minkara.carview.co.jp/userid/124081/blog/p2/ といったように今までどおりページ数を付ければ O.K. です.また,カテゴリ別に全部読み込むには
http://minkara.carview.co.jp/userid/124081/blog/c2863/ から順に行けます.
この
c2864 というカテゴリ番号は全ユーザ共通のもので,私が何番を持っているかとか,そのカテゴリが私にとって何番目かとかが判らないという問題は残っていますが,以前と較べると大きな改善です.
どうして以前の方式に文句を言っていたか? 前回も書きましたが,それはバックアップを容易に取れないためです.以前の方式だと,私が記事の中に張った記事のリンクが,自分のものなのか,他人のものなのか,一切区別が付きませんでした.改善後は,必ず自分のユーザ ID (私なら 124081) が URL に入りますので,誰が書いた記事か,明確に区別可能です.
これを利用して,今回,私が過去に投稿したすべての記事・画像をローカルにバックアップすることが出来ましたので,方法を紹介します.ツールは,GNU の
wget を使いました.この手の再帰的 html ファイルダウンロードツールはいくつかあるのですが,使いやすいものがなかなかなく困っていました.でもそれを知らないのは私だけだったようで
(^^; wget は私の要望にぴったり.
……紹介というか,
wget の存在を初めから知っている方や,Linux が自由に使える環境にあって私同様にデータのバックアップを取りたいと思っている方は既にご自身で解決しているでしょうから,どちらかと言うと自分用の備忘録です :-) なので,作業内容のポイントだけ書いて,敢えて詳細な説明はしていません.
まずは
wget を使ってデータをダウンロードします.使った
wget のバージョンは 1.10.2 でした.
%wget -r -k -np -p -H -l 110 -D carview-img01.bmcdn.jp,carview-img02.bmcdn.jp,img01.carview.co.jp,minkara.carview.co.jp,carlife.carview.co.jp,auction.carview.co.jp http://minkara.carview.co.jp/userid/124081/
-r : 再帰的にファイルを取得
-k : ダウンロードしたファイル中のリンクをローカルファイル間での相対リンクに変換する
-np : 親ディレクトリは取得しない (私のページ以外に行かないようにするため)
-p : 画像ファイル等のページ構成要素をすべて取得する
-H : 他のホストにあるファイルも取得する
-l : リンクをたどる数
-D : このドメインに関してのみリンクをたどる
とコマンドを与えます.私の環境では,15 分くらいで 1,200 程度の記事がダウンロード出来ました (以下で追加して取得したファイルを含め,全部で 5,500 ファイル・230MB ほどになりました).
「みんカラ」では,上記の
/pN/ の形式でページがたどれるのは 100 ページまでなので,ネストレベルは 110 としてあります.まだ記事をあまり投稿していない人はもっと小さい値でも大丈夫ですが,
「月」ごとのページが途中までしかダウンロードされなくなるので,適宜調整が必要です (逆に,ネストを深くし過ぎるとゴミも多くダウンロードする可能性が高くなります).
「みんカラ」のデータは
minkara.carview.co.jp 以外に
carview-img01.bmcdn.jp と
carview-img02.bmcdn.jp,
carlife.carview.co.jp,
img01.carview.co.jp (携帯から投稿した記事の画像保管用),
auction.carview.co.jp とに分散しているので,それぞれを探索範囲に含めます.ただし,私はみんカラオークションは使っていないので,
みんカラオークションのページは無視しました (このページがどう "成長" するのか,面倒なので調べていないのですが,ここは自分のページがまったく違うサブドメインにあるので,これもきちんとダウンロードしようとするとかなり設定に苦労すると思います).……要するに結局,自分が投稿したデータがすべて
http://minkara.carview.co.jp/userid/124081/ 以下にある訳じゃないんですよね... その意味では,改善はされたものの,コマンドを与えれば一発で根こそぎダウンロードという状態からはまだ遠いです(´・ω・`)
さて,これだけでデータはほぼ問題なくダウンロード出来たのですが,CSS に大問題があります.「みんカラ」のスタイルシートは,
<link rel="stylesheet" href="/userid/124081/css/default.aspx?n=C1" type="text/css" title="default">
と定義されており,別ファイルで提供されています.さらに,スタイルシートをあらかじめ用意されているテンプレートではなく,私のようにカスタマイズして使っていると,上記のようにこのファイルが引数を必要とする CGI の結果として得られるため,ローカルに落とすとこのファイルを適切に読んでくれません (例えばデフォルト状態のままであればこの部分は
/styles/Blue.css となって何にも問題ありません).何かうまい方法があるのかも知れないのですが,面倒なので私は,ダウンロードした CSS ファイルへ
default.aspx という名前でシンボリックリンクを張り,次のようなスクリプトを書いてシンボリックリンクを参照するように置換してしまいました (以下のスクリプトではオリジナルファイルは消しています).
cnvCss
#!/bin/csh
foreach i ( html aspx )
foreach j ( `find . -name "*.$i" -print` )
sed -e 's|\(/css/default\.aspx\)\?n=C1\"|\1\"|' $j > $j.new
mv $j.new $j
end
end
これでだいぶ完全なダウンロードに近づきましたが,まだふたつの問題が残りました.ひとつ目はこの CSS ファイルで定義している画像.CSS で
#Footer {
background: url('http://carview-img02.bmcdn.jp/carlife/images/UserCarPhoto/65481/p1.jpg') no-repeat;
width: 750px;
height: 100px
}
のように URL (正確には URI かな.でも,CSS でのキーワードが
url なので,ここでは URL と表記します) で指定している画像ファイルを (URL が記述されているのが .html ではないため?),冒頭の
wget コマンドでは取得してくれません.このためだと思いますが,CSS ファイル内の URL 記述も
wget の
-k (--convert-links) オプションを付けても置換されませんでした.そこで,CSS ファイルに記述されている URL を自動的に抽出し,
wget で改めて取得するとともに,CSS ファイル内の URL 記述もローカルへの相対パスに書き換えてしまうこととしました.
もうひとつの問題は,オリジナル画像ウィンドウへのリンク.せっかく,
http://minkara.carview.co.jp/userid/124081/ といったユーザごとの URL (自 URL) が与えられたのですが,上記のように,「みんカラ」ではオリジナル画像ウィンドウ (記事中に掲載されている縮小画像ではない,投稿オリジナルサイズの画像表示画面) は
http://minkara.carview.co.jp/image.aspx?src=http://carview-img01.bmcdn.jp/carlife/images/UserDiary/8501126/P1.jpg のような CGI の呼び出しとなっており,しかもこれは自 URL 外です.このため,CGI ページそのもののダウンロードはあきらめるとしても,いくつか試した設定ではオリジナル画像の一括ダウンロードが出来ませんでした.
そこで,CSS の問題とオリジナル画像の問題を解決すべく,以下のようなスクリプトを書いて別途書き換え・ダウンロードしました (このスクリプトでは
wget の呼び出しまで一挙に行ない,ダウンロードするための URL ファイルも削除してしまっています).実際には,これらの動作を確認した後,一番最初に載せた
wget の呼び出しと,
cnvCss スクリプトもひとつにまとめ,一発ですべて終わらせています.
getImageFiles
#!/bin/csh
if ( -f ./$$.url.tmp ) rm ./$$.url.tmp
foreach i ( html aspx )
foreach j ( `find . -name "*.$i" -print` )
egrep -e 'href=\"http://minkara.carview.co.jp/image.aspx\?src=' $j | sed -e 's/^.*href=\"//' -e 's/^\([^\"]*\)\" .*$/\1/i' >> ./$$.url.tmp
end
end
sed -e 's/http:.*src=//i' -e 's/%3a/:/ig' -e 's/%2f/\//ig' ./$$.url.tmp | sort | uniq > ./$$.url.txt
egrep carview-img ./minkara.carview.co.jp/userid/124081/css/default.aspx\?n=C1 | sed -e "s/^.*url('//" -e "s/').*//" | sort | uniq >> ./$$.url.txt
sed -e 's|http://\(carview-img02\)|../../../../\1|i' ./blog/userid/124081/css/default.aspx\?n=C1 > ./$$.tmp
mv ./$$.tmp ./blog/userid/124081/css/default.aspx\?n=C1
wget -nv -p -i ./$$.url.txt
rm ./$$.url.txt ./$$.url.tmp
なお,Linux 環境によってはなぜか
sed の
i オプションを付けているとエラーになりました (太字.なんでだろー?).また,環境によりオリジナルファイルをいったん文字コード変換しないと
sed 置換がうまく動作しないかも知れません.
これにより,まだオリジナル画像ウィンドウへのアクセスは実現出来ていませんが (サーバを使えば簡単ですが,あくまでも単なる html ファイルのリンクで実現するのは難しい?),少なくとも私が投稿したデータをすべてバックアップ出来ました
(^^)/
このようにして,みんカラへこれまでアップロードしたデータ群をダウンロードし,これを私が借りているサーバーに置くことにより,
こんな感じでミラーサイトを構築出来ました.なお,みんカラのファイルは原則として .html ですが,一部ページは .aspx となっているので (こんなの,.html として見せてくれればいいだけなのになぁ),
.htaccess
AddType text/html .aspx
として,.aspx も .html と同じで扱えるよう MIME タイプを追加しています.もちろん,これは一度だけやればよい作業です.
ミラーサイトは,見た目は URL 以外,本家サイトと同じですが,私のページに関してはみんカラ (carview) のサーバを (恐らく
(^^;) オリジナルサイズ画像表示ページを除いて,いっさい使わずに動作しています.
このように Web サーバ上に置いての閲覧だけでなく,PC の HDD に格納したファイルを直接アクセスして閲覧することも出来るので,ネット接続出来ないけれど時間を持て余しているといったとき,オフラインでファイルを閲覧して校正・推敲をしたり出来て便利です.
それはともかく,何しろタダのサービスである「みんカラ」.いつ carview がへそを曲げてサービスを停止したり,私の ID を一方的に削除したり,あるいはサーバが飛んでリストアも不能という自体に陥るか判りません.せっかく,これまで 3 年以上にわたって 1,200 弱の記事を書いて私のカーライフを記録して来たのに,それが一瞬にして失われるかも... と考えたら不安になりますが,今回試した方法でほとんど手間をかけずにバックアップ可能なことが判りました.ときどき実行して,バックアップしておきたいと思います.
また,ブラウザで問題なく閲覧出来るかどうかは別として,ローカルにすべてのデータを保存出来たことにより,自分が投稿した記事の検索が非常に簡単になります.例えば,私は "顔文字" の一部の種類は固定ピッチフォントを使ってこんな感じ「
(~_~;」に書くことにしているのですが,フォント指定を忘れてこんな感じ「(~_~;」になっているものが所々ありました.
Google は単純な
grep とは違うので,こうした漏れを見付けるのには使えません.ローカルファイルに全データが保存出来ていれば,自由に検索可能となりますので,漏れの検索と修正も容易になります.……って,誰もそんなん気にしないか (汗
このほか,
「みんカラタグ」は,同じタグを付けている記事を一覧することが出来ますが,自分が書いた記事だけを抽出するということが出来ません.しかし,ローカルに保存したファイルから検索すれば簡単です.時間が取れたら,タグから各記事にリンクを張ったページを作りたいなぁと思っています (ミラーサイト特有コンテンツですね).……てか,まずは blog 部分のみでパーツレビューには未対応ですが,勢いでそのページも作ってしまいました
(^^;
こちらが私の記事に付いているみんカラタグインデックスページです.このように一覧出来るようにしてみると,スペルミスなど不適切なタグ付けも簡単に判り,修正・統一も容易になります.……ってこれも,誰もそんなこと気にしてないか (爆
このために作ったスクリプト群も一応載せておきます.まずは,メインスクリプトはこんな感じ.ここでは
_makeTagHTML という
Perl スクリプトで .html を解析し,blog タイトルとみんカラタグを取得します.それをみんカラタグ順,かつ,記事の古い順に並び替えて,
_cnvTagFile という
awk スクリプトで HTML の形に整形しています.
makeTagHTML
#!/bin/csh
if ( -f ./$$.log ) rm ./$$.log
foreach i ( `find . -name 'index.html' -print | egrep -e '/blog/[0-9]+/' | sort -g -t / -k 6` )
./_makeTagHTML $i | nkf >> $$.log
end
sort $$.log | awk 'BEGIN{FS="] <";}{print $1 "] <" $3}' > $$.txt
awk -f _cnvTagFile $$.txt > tag.html
rm $$.log $$.txt
メインスクリプトから呼び出される
Perl・
awk スクリプトはそれぞれこんな感じ:
_makeTagHTML
#!/usr/bin/perl
$TitleString = "- Recorder 【 みんカラ 】 ブログ";
$FileName = $ARGV[0];
#-----------------------
# blog title の取得
#-----------------------
do {
$_ = <>;
} while ($_ !~ /<title>/);
# この処理は不要だが,念のため
do {
$_ = <>;
die "Fatal error: Can't find the title of blog. \n\n" if (/<\/title>/i || eof);
} while ($_ !~ /$TitleString/i);
s/^[\t ]*//; # 前側除去
s/$TitleString//; # 後側除去
s/\s*$//; # 改行コード除去
$BlogTitle = $_;
#-----------------------
# みんカラタグの取得
#-----------------------
do {
if (eof) {
$_ = "<div class=\"TrackBackUrl\"><a href=\"http://minkara.carview.co.jp/tag/0000/\">(タグなし)</a></div>";
} else {
$_ = <>;
}
} while ($_ !~ /<div class="TrackBackUrl"><a href="http:\/\/minkara\.carview\.co\.jp\/tag\//i);
s|<div class="TrackBackUrl">||ig;
s|<a href="http://minkara\.carview\.co\.jp/tag/[0-9]+/">||ig;
s|</a>||ig;
s| | |g; # セパレタ変換
s|</div>||ig;
s/\s*$//; # 改行コード除去
@TagList = split(/[ \t]+/);
#-----------------------
# 記事番号の整形
#-----------------------
$ArticleNum = $FileName;
$ArticleNum =~ s|^.+blog/||;
$ArticleNum =~ s|/index\.html||;
# 同一タグ内は記事番号順になるよう,./blog/userid/124081/blog/123456/index.html
# というファイル名から 123456 部分を取り出し,最後に 0 プレフィックスで出力する.
#-----------------------
# 結果出力
#-----------------------
for ($i = 0; $i < scalar(@TagList); $i++) {
printf("[%s] <%07d] <A HREF=\"%s\" TARGET=\"_blank\">%s</A>\n", $TagList[$i], $ArticleNum, $FileName, $BlogTitle);
# 記事番号を 0 プレフィックスにするのは sort コマンドの複数フィールドソート
# (文字列+数値) を簡単に行なうため.ここで出力したのはあくまでもソート用で,
# 最終的には不要なので親スクリプトの makeTagHTML 内で削除する.
}
_cnvTagFile
BEGIN {
FS = "] <";
printf("<HTML>\n <BODY>\n");
}
{
gsub(/^\[/, "", $0);
if (NR == 1) {
printf(" <B>%s</B><BR>\n<%s", $1, $2);
old = $1;
} else {
if (old == $1) {
printf(" <%s", $2);
} else {
printf("<BR><BR>\n");
printf(" <B>%s</B><BR>\n<%s", $1, $2);
old = $1;
}
}
}
END {
printf("\n </BODY>\n</HTML>\n");
}
なお,元々の目的であったバックアップについては,
cron で定期的に実行してしまうのも手ですが,わずかですがまだ手作業が若干残っているので,まずはこれを自動化するのが先かな.とはいえ,定型的な作業なので,比較的簡単にスクリプト化は出来そうです.そのうちまた時間が取れたらやりましょう.