2015年10月7日水曜日

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マニュアル

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

Java初心者がはまったこと2(ラッパークラス)

こんにちは。Java初心者のWebエンジニアKです。
PHPのノリでJavaを書いていたらはまったこと第二弾として、今回はラッパークラスについて書きたいと思います。

■intとIntegerではまる

Javaのソースコードを見ていると、例えば数値を扱う変数を作るとき、以下の2通りの宣言があることに気付きました。
int num = 100;
Integer num2 = 100;
両者の違いを正しく理解せずに、その日の気分で使い分けていたら見事にはまりました。

■intとIntegerの違い

intはプリミティブ型のひとつで、値(intの場合は特に数値)のみを扱うための型です。 初期値は0です。
一方Integerはラッパークラスと呼ばれる参照型のひとつで、intを値だけでなく「振る舞い」も合わせて扱えるように定義した型となります。
「振る舞い」は平たく言うとクラスメソッド(toStringやvalueOf)のことですね。

また、Integer型は参照型のため値にnullを取ることができ、初期値も0ではなくnullになります。
ここが個人的なはまりポイントでした。
両者の違いをまとめてみると、
  • Integerは値にnullもとれる
  • Integerの初期値はnull、intは0
  • IntegerにはtoStringやvalueOfなどのメソッドが実装されている
javaのラッパークラスはint:Integer以外にもboolean:Booleanなど8種類あります。
両者の違いを理解して、要件にあった使い分けをすることが重要ですね。
参考サイト

Java初心者がはまったこと(文字列比較)

はじめまして。WebエンジニアのKと申します。
これまでサーバサイドはほぼPHPで実装してきましたが、最近ではJavaへの挑戦も始めました。
慣れたPHPの感覚でJavaを書き始めると、思わぬところではまってしまうことがあり、
ここでは自戒の念を込めてはまったポイントを記しておこうと思います。

■文字列比較ではまる

こんなif文を書いて、判定がtrueとならず、頭を悩ませていました。
※str = “hoge”だと、この単純な例の場合たまたま判定がtrueになってしまうので、わかりにくいですが”hog”と”e”にわけて宣言しています。【参考
String str = "hog";
str += "e";
if (str == "hoge") { // false...
    // do something
}
PHPだと文字列はプリミティブ型なので、上記のような文字列が格納された変数(str)と文字列リテラル(“hoge”)の比較でうまくいくのですが、
Javaの場合だと文字列は参照型で、文字列リテラルも一見プリミティブのように見えますが、内部ではString型のオブジェクトとして扱われます。
イメージとしては以下のようにStringクラスをnewしている形ですね。
String str = new String("hoge");
※ただ、これはあくまでイメージで、本当にこの書き方をすると文字列リテラルから変換されたString型オブジェクトを、さらにStringクラスのコンストラクタに渡していることになるので、二度手間となってしまいます。

“hoge”がString型のオブジェクトだとわかれば、比較演算子(==)でtrueとならないことを受け入れることができました。

■結局

で、結局どうすればよかったというと、Stringクラスに実装されている文字列比較用のメソッド”equals”を使いましょうというお話でした。
String str = "hog";
str += "e";
if (str.equals("hoge")) { // true!
    // do something
}
なんとなく見よう見まねで書けても、きちんと入門書などで言語仕様を把握しておくことが重要だと痛感した一日でした。

Registerでのカスタムコントロールの関連付けを、Web.configにまとめる

こんにちはYです。
ややこしいタイトルを付けてしまいました。

Webページを作成していて、ユーザーコントロール(.ascxファイル)を作成し、
目的のページに関連付けて使用できるようにすることってよくありますよね?

その時はAspxファイルの上部に↓のように書くと思います。
■ASP.NET ページでユーザコントロールを参照する方法
<%@ Register TagPrefix="includes" TagName="BenriControl" Src="~/control/BenriControl.ascx" %>


これをすべてのページの範囲で使用できるようにするのが今回の目的です。
■web.config ファイルでユーザコントロールを参照する方法
Web.configファイルの
<pages>
 <controls>
  ~
 </controls>
</pages>

上の「~」の位置に
<add tagprefix="includes" tagName="BenriControl" src="~/control/BenriControl.ascx" />
を追加します。

すると、Web.configを読み込んだ段階でコントロールの関連付けが完了するのです。

2015年10月6日火曜日

指定の文字数を取得する


こんにちはYです。
SEO対策をしていて、ちょっと文字が多いな、、、と感じた箇所にぶつかりました。
データもとの文章を変更せずに、先頭の~文字で切って妥協することにしました。
その時の対処方法です。

String.Substring メソッドを使用しました。

String nagaiMoji = "Hello World!"
String moji = nagaiMoji.Substring(1, 6);

上記の場合の出力は「ello W」となります。

これを使用して、String moji = nagaiMoji.Substring(0, 99);
100文字分を取得するようにと書くことができました。