ラベル リンク切れ の投稿を表示しています。 すべての投稿を表示
ラベル リンク切れ の投稿を表示しています。 すべての投稿を表示

2015年10月7日水曜日

wgetでサイト内のリンク切れチェック(いろいろ実験)

以前、wgetでサイト内のリンク切れチェックの記事でwgetのspiderオプションを紹介しましたが、実施するにあたって
  • 「-recursive -level 1」とすると指定ページだけチェックして終わり?もしくは指定したページからリンクされたページまで辿る?
  • 同一URLのリンクが複数貼られていた場合、毎回チェックしにいくのか
  • リダイレクトされるURLの場合、リダイレクト先まで追ってくれるのか
  • 一斉に大量のリクエストを送ってサーバに負荷をかけ過ぎないか
のような疑問が浮かんだので、実際に実験してみました。

準備

以下の様なリンク構造を持ったサイトを用意しました。



やかましい矢印は他ページへのリンクを表しています。/detail/4.htmlからはトップページ(index.html)へ302リダイレクトするようにしています。

結果


-recursive -level1でどこまでリンクを辿るのか

wget --spider --no-directories --background -o test.log --recursive --level 1 --no-verbose --execute robots=off http://localhost/index.html
上記コマンドを実行したところ、以下の様なアクセスログになりました。
127.0.0.1 - - [17/Sep/2015:19:15:56 +0900] "HEAD /index.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:15:56 +0900] "GET /index.html HTTP/1.1" 200 66
127.0.0.1 - - [17/Sep/2015:19:15:56 +0900] "HEAD /list/1.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:15:56 +0900] "GET /list/1.html HTTP/1.1" 200 111
127.0.0.1 - - [17/Sep/2015:19:15:56 +0900] "HEAD /list/2.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:15:56 +0900] "GET /list/2.html HTTP/1.1" 200 4340
-level 1とすると、指定ページから貼られているリンクだけチェックするようです。

同一URLのリンクが現れた時、毎回チェックするのか

-level 3と指定して実行したところ、以下の様なアクセスログになりました。
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /index.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /index.html HTTP/1.1" 200 66
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /list/1.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /list/1.html HTTP/1.1" 200 111
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /list/2.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /list/2.html HTTP/1.1" 200 148
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /detail/1.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /detail/1.html HTTP/1.1" 200 180
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /detail/2.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /detail/2.html HTTP/1.1" 200 180
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /detail/3.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /detail/3.html HTTP/1.1" 200 180
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /detail/4.html HTTP/1.1" 302 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /index.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /index.html HTTP/1.1" 200 66
一度チェックしたURLは再度現れても省略されるようです。これは助かります。
ただ、パラメータが付くURLの場合、その順番が若干ずれるだけで別URLとみなされるので、
URLの埋め方によっては効率が悪くなってしまいますね。

リダイレクト先まで追ってくれるのか

先ほどのアクセスログにもありますが、リダイレクト先も追ってくれます。これも助かります。
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /detail/4.html HTTP/1.1" 302 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "HEAD /index.html HTTP/1.1" 200 -
127.0.0.1 - - [17/Sep/2015:19:20:32 +0900] "GET /index.html HTTP/1.1" 200 66
ただし、リダイレクト後のURLはチェック済みであっても再度確認しにいくようですので、注意が必要です。

サーバへの負荷は大丈夫か

パラメータだけ異なるリンクを100個ほど増やして試してみたところ、今回の環境(windows上に立てたapache)では65req/secほどでした。
通常のwebサイトでは問題なさそうですが、ページごとの処理内容やサーバのスペックにもよるかと思いますので、
参考程度として頂けたらと思います。

wgetでサイト内のリンク切れチェック

主にリソースのダウンロードに多用するwgetコマンドですが、オプションの指定の仕方によってリンク切れチェッカーとして使えることがわかりました。
社内サーバやベーシック認証がかかっている環境にも適用可能で、cron等のタスクスケジューラにも登録しやすいので、
開発の最終フェーズから、日々のサイト内リンクの死活監視まで幅広く重宝すると思います。

■コマンド

色々なオプションがありますが、実際に使ったコマンド例をご紹介します。
$ wget --spider --no-directories --background -o {YOUR_LOG_PATH} \
--recursive --level 3 --no-verbose --execute robots=off \
--user={YOUR_ACCOUNT} --password={YOUR_PASSWORD} \
--user-agent="Mozilla/5.0 (iPhone; CPU iPhone OS 8_0 like Mac OS X) AppleWebKit/600.1.3 (KHTML, like Gecko) Version/8.0 Mobile/12A4345d Safari/600.1.4" \
http://{YOUR_SITE_URL}
また、実行した環境は以下のとおりです。(Windows7 Cygwin)
$ uname -a
CYGWIN_NT-6.1 STCOM1053 2.2.1(0.289/5/3) 2015-08-20 11:42 x86_64 Cygwin
$ wget --version
GNU Wget 1.16.3 built on cygwin.
各オプションについて解説していきたいと思います。

■各オプションについて


–spider

ファイルの存在チェックのみ行い、ダウンロード(保存)を行わないようになります。(実際は保存してから削除している模様)
webサーバのアクセスログを見ると、まずHEADでリクエストし、200が帰ってきたら再度GETでリクエストといった挙動のようです。

–no-directories

–spiderオプションによりファイルの保存はされませんが、このオプションを指定しないと空ディレクトリが掘られてしまいます。
消すのも手間なので、指定したほうが無難かと思います。

–background

バックグランドのタスクとして実行されます。
サイト内を再帰的に巡回するケースだと、サイト規模にもよりますが長時間かかると思われるので、
コンソールが落ちても中断されないようにします。

-o {YOUR_LOG_PATH}

ログを出力するファイルパスを指定します。
コマンドラインに垂れ流しだとすぐに流れてしまいますので、別ファイルに書きだしたほうが良いでしょう。

–recursive –level 3

–recursiveで再帰的にリンクを辿るようになります。
–levelでどの階層まで辿るかを指定します。値が大きくなればなるほど実行時間が飛躍的に長くなりますので、徐々に探っていくといいと思います。
–levelを指定しないと無限にリンクを辿ります。

–no-verbose

ログの詳細情報を省略するようになります。
リンクの死活チェックだけであれば、ログファイルの容量圧縮のためにも省略して問題ないでしょう。

–execute robots=off

robots.txtの制限を無視するようになります。

–user={YOUR_ACCOUNT} –password={YOUR_PASSWORD}

ベーシック認証のユーザ名とパスワードを指定します。
認証をかけていない公開サーバであれば、このオプションは不要です。

–user-agent=”Mozilla/5.0…

各リンクにアクセスする際のユーザエージェントを指定します。
スマートフォン向けサイトを確認する場合などに指定します。
デバイスに関係のないサイトであれば、このオプションは不要です。

http://{YOUR_SITE_URL}

対象サイトの起点となるURLを指定します。通常はトップページになるかと思います。
URLはコマンドの一番最後に指定する必要があります。

■結果の確認方法

リンク切れがなかった場合、以下の様なメッセージがログの末尾に出力されます。(日本語の場合)
壊れたリンクはありませんでした。
終了しました –2015-09-12 18:58:36–
経過時間: 0.02s
ダウンロード完了: 3 ファイル、288 バイトを 0s で取得 (3.11 MB/s)
リンク切れがあった場合は以下の様なメッセージになります。
1 個の壊れたリンクを見つけました。
http://localhost/detail/4.html
終了しました –2015-09-12 19:01:37–
経過時間: 0.04s
ダウンロード完了: 6 ファイル、574 バイトを 0s で取得 (4.06 MB/s)
上記の場合、http://localhost/detail/4.html がリンク切れということになります。
しかし残念なことに、そのリンクがどのページから貼られているのかは、これだけではわかりません。
ひとつの解決策として、対象のwebサーバのアクセスログにリファラを出力するようにすれば、
リンク元特定の手助けになるかもしれません。(wgetはREFERRERヘッダも送信してくれるようです。)
参考サイト
wgetマニュアル

続き:いろいろ実験しました