未分類

今回は、wgetの–level(リンクの最大深さ)と–convert-link(オフライン閲覧用のリンク修正)の内容を検証する。

対象はGNU Wget 1.20.1。

–level(リンクの最大深さ) の検証

ここでは、最大範囲まで辿られると、時間が増えないことを検証する。

クロール先の作成

HTMLを生成するshellスクリプト

COUNT=$1
BASE_URL="https://elephantcat.work/wget_test"
for i in `seq $COUNT`;do
        FILE="$i.html"

        echo "<html lang=\"en\">" > $FILE
        echo "<body>" >> $FILE
        echo "<ul>" >> $FILE
        MAXJ=`expr $i + 1`
        for j in `seq $MAXJ`;do
                URL="$BASE_URL/$j.html"
                echo "<li><a href=\"$URL\">$j</a></li>" >> $FILE
        done
        echo "</ul>" >> $FILE
        echo "</body>" >> $FILE
        echo "</html>" >> $FILE
done

上記を実行して、50個分のHTMLを生成

$ sh create_htmls.sh 30

カレントディレクトリに1.html~30.htmlが作成されます。例えば3.htmlは以下のようなものになります。

<html lang="en">
<body>
<ul>
<li><a href="https://elephantcat.work/wget_test/1.html">1</a></li>
<li><a href="https://elephantcat.work/wget_test/2.html">2</a></li>
<li><a href="https://elephantcat.work/wget_test/3.html">3</a></li>
<li><a href="https://elephantcat.work/wget_test/4.html">4</a></li>
</ul>
</body>
</html>

3.htmlは4つのリンクを持つHTMLファイルです。同様に、n.htmlは、n+1個のリンクを持つHTMLファイルであり、1.htmlから1つずつリンクを辿る度にファイルが増えるようなネットワーク構造になっています。

測定

1.htmlを起点にレベル1つずつ増やしながら、50回時間を計測します。測定用のスクリプトが以下になります。

for i in `seq 50`; do
        rm -r elephantcat.work/wget_test
        /usr/bin/time --quiet -f %e wget --quiet --recursive --level $i --page-requisites --adjust-extension --span-hosts --convert-links --restrict-file-names=windows --domains elephantcat.work --no-parent https://elephantcat.work/wget_test/1.html
done

実行すると標準出力に実行時間が1行ずつ出るので、リダイレクトしてファイル(time.log)に落とします。

$ sh measure.sh > time.log

後はExcelなどでグラフにすればOK。今回は遊びで、PerlのText::Chartを使ってみました。

use Text::Chart qw(gen_text_chart);

chomp(my @nums=<STDIN>);
my $res = gen_text_chart(
    data => \@nums,
    chart_height => 10,
    type => 'sparkline',
);

binmode(STDOUT, ":utf8");
print $res;

これを使うとテキストで棒グラフが書けます(整形が結構大変)。

結果と考察

                                █  ▄         █     2[秒]
                             ▃▁ █▅▂█▆▂ ▄▃▂▄▂▂█▆▃▂▁
                         ▃▂  █████████▇███████████
                         ██▃▄█████████████████████
                    ▂▂▁▃▇█████████████████████████
               ▁ ▁▂▄██████████████████████████████ 1
             ▅▆█▇█████████████████████████████████
         ▂▃▄▇█████████████████████████████████████
     ▂▃▅▇█████████████████████████████████████████
 ▂▄▆██████████████████████████████████████████████ 
回数     10        20        30        40        50

30回以降横ばいに見えます。レベルは最大回数を超えると取得時間が頭打ちになるということです(当然ですが)。

–convert-link(オフライン閲覧用のリンク修正)の内容検証

前節で生成し、wgetで取得した3.htmlを見てみます。

<html lang="en">
<body>
<ul>
<li><a href="1.html">1</a></li>
<li><a href="2.html">2</a></li>
<li><a href="3.html">3</a></li>
<li><a href="4.html">4</a></li>
</ul>
</body>
</html>

上にあるものと比べると、絶対URLだったリンクURLが、相対URLになってることが分かります。絶対URLでないのは、オフライン閲覧した際にリンク切れになってしまうからです。このように、オフライン閲覧などを考慮すると、(元のサイト次第ですが)HTMLの書き換えが必要となります。以降では絶対URL→相対URLの書き換え以外のリンク書き換えパターンを見ていきます(全部ではありません)。

ディレクトリ

例えば、https://elehantcat.work/、これにもファイル名がありません。通常、この内容はtext/htmlであり、多くの場合、index.htmlやらindex.phpやらindex.jspやらindex.jsやら、拡張子は違えど、共通してindex.*という形式の名前のファイルが処理していることが多いと思います。wgetでは、ディレクトリの内容を取得すると、ファイル名にはindex.htmlを使用します。リンクURLは当然ただのディレクトリなので、オフライン閲覧のためには書き換えが必要になります。

拡張子なし

例えば最近の動的に生成されるページでは、URLを見てコントローラを選ぶルーティング機能を導入しているフレームワークが多いです。そのようなフレームワークを使用すると、URLとコントローラなどが必ずしも一対一対応しないので、URLのファイル名部分に拡張子が付かなくなります。

これらのURLからファイルとして内容をダウンロードした場合、拡張子のないファイルは見た目で何のファイルか分からず、扱いに困ります。そこで、wgetではオプション(–adjust-extension)でContent-Typeから拡張子を付けてくれる機能が追加されています。このようなケースではリンク元は拡張子がついていないため、オフライン閲覧用に書き換えが必要になります。

その他

他にもいろいろありますが、あとは自分で見つけてください。マニュアルは、以下にあります。

https://www.gnu.org/software/wget/manual/wget.html

最後に

–convert-linkによるリンク書き換え処理は全部ダウンロードが終わってからなので、Ctrl+Cで止めると書き換えずに終わってしまいます。ご注意ください。

未分類

今どきオフライン作業なんてあんまりないけど、wgetって単独ファイルだけでなく、JavaScriptなどで作られてない静的なリンクなら辿って次を取得することもできる。昔の貧弱なネットワークの頃は重宝した。

取得してみる

とりあえずこのサイトをwgetで取得してみる。パラメータは以下のサイトを参考にした。(–domains指定は–span-hostsと同時指定禁止なので除外)

shell – How to download an entire site with wget including its images – Super User

$ wget --recursive \
--level 5 \
--page-requisites \
--adjust-extension \
--span-hosts \
--convert-links \
--restrict-file-names=windows \
--domains elephantcat.work \
--no-parent \
elephantcat.work

上記コマンドを実行すると、elephantcat.workから、再帰的に5段階までリンクを辿り、同一ホスト内の全ページをローカルファイルに保存してくれる。保存する際には、ホスト名のディレクトリ下にURLから想定される名前で保存される。HTML内には埋め込まれる要素やリンクなどもあるが、静的なものは残らず解析して取ってきてくれる。クエリなどがあっても、URIとして区別されればちゃんとそれをファイル名にして保存される。

オプション説明

オプション意味
–recursive再帰的に取得
–level 数字指定された深さまで再帰的に取得
–page-requisites画像など HTMLを適切に表示するために必要なすべてのファイルを取得
–adjust-extensionMIMEタイプなどを元に拡張子を自動で修正する
–span-hosts同一ホスト内の リンク のみ辿る
–convert-links同一ホストへのリンクを相対リンクに書き換える
–restrict-file-names=windowsファイル名の大文字/小文字統一や使用禁止文字のエスケープに使用するモードの指定
–domains指定ドメイン以外を取得しない
–no-parent親ディレクトリ側へのリンクを辿らない

注意事項

重要なのは探索範囲と時間に大きく影響する–levelと、–convert-links。

–levelはサイトの大きさやクロール可能な時間に合わせて適宜修正が必要。全ての経路を辿れる深さ以上を指定しても取得時間は増加しない。

ダウンロードされたファイルは必ずしもURLとおりの構成にできるわけではないので、–convert-linksはダウンロードしたファイルをオフライン閲覧できるよう、 HTMLの中身を書き換えることを意味している。そして、この処理は、指定した範囲のファイルを全て取得し終わった後、最後に行われるので注意。「時間かかるからこの辺でやめる→Ctrl+C」とかするとこの変換はかからない。