2015年10月27日火曜日

robots.txtの書き方



こんにちは山田です。
肌寒くなってまいりましたね。10月も、もう終わりです。
秋の味覚の栗を探したい気持ちを抑えつつ、SEO対策の話です。

今回は、クロール最適化の方法の一つとして、robots.txtについてお話しします。
まず、検索エンジンのロボットが、サイトの中で最初にアクセスするファイルがrobots.txtになります。

もし、テストページなどをアップロードしてクローラーにインデックスされたくない場合は
robots.txtで拒否して、インデックスしてお欲しいページに誘導してあげましょう。

さて、以下に書き方についてまとめてみました。ご参考になればと思います。


robots.txtの書き方

■ファイル名
robots.txt

■ファイルの置き場所
ドメインのルートドメイン

■サイト内すべてのロボットを拒否したい場合
User-agent:* 
Disallow:/

■特定のロボット+特定のディレクトリやページ
User-agent: Googlebot ←グーグル
Disallow: /test/    ←拒否したい場合
Allow: /test/act    ←testディレクトリは拒否するが、actページは受け入れる場合
Allow: /test/act.html ←testディレクトリは拒否するが、actページは受け入れる場合

ser-agent: bingbot  ←Being(複数ロボットの場合は改行を入れて。拒否ページを記述する)
Disallow: /test/    

■ついでにsitemap.xml
ここに記述しておくとSitemapを読むようになってくれるので記載しておいたほうが良いです。
書き方は↓

Sitemap: http://www.test.com/sitmap.xml
  

2015年10月26日月曜日

「datepicker」の色々。

こんにちわ、開発者のⅠです。
先日、北海道では雪が降ったそうです。
その他の地域も急に冷え込んできましたが、みなさん体調はいかがでしょうか?

さて、前回の投稿ではお伝えできなかった、「datepicker」の各プロパティについて補足しようと思います。

このプロパティに任意の値 ( と言っても、それぞれ選択肢は限られておりますが…… )を設定することで、希望のデザインにカスタマイズすることが可能です!

例えば、”numberOfMonths” というプロパティでは一度に表示するカレンダーの数を指定できます。

「1」を指定すれば一ヶ月分、「2」を指定すれば二か月分……という感じですね。

まだまだ他にもプロパティは存在しており、

   「changeMonth : true(”月”を変更できる) / false(変更不可)」

  「changeYear : true(”年”を変更できる) / false(変更不可)」

   「firstDay : 0 (週始まりが”日曜日”) / 1 (週始まりが”月曜日”)」

   「yearRange : c-10:c+10 (”現在”を基準に選択できる範囲を指定)」

といったプロパティもあります。

これ以外にも、「これいつ使うの?」という用途が想像できないプロパティも存在します。
気になった方はぜひ調べてみてください!

それでは、今日はここまでです。



2015年10月23日金曜日

サーバーコントロールの属性を書き換える方法

どうも山田です。

ASP.NET環境で開発を行っているシステム屋です。
デザイン側の属性を書き換える方法の覚書です。
意外と便利です。

aspx
 <a href="#" class="btnNegative" runat="server" id="linkToTop">

C#
lintToTop.Attributes.Remove("href");
lintToTop.Attributes.Add("class", "btnDisabledNotGray m20");
lintToTop.Attributes.Clear();

①href属性を削除
②class属性を上書き
③すべての属性を削除

Bloggerでインデックスステータスがずっと0 その1

お疲れ様です。岡田です。

ちょうどひと月前の9月末にブログをBloggerへ移設してきたのですが、標題のとおり、Search Consoleで見れる「インデックスステータス」がずーーーーーーっと0になっているので、気になっていました。
序盤はコンテンツが少ないですし、新しいサイトなので、クローラーが来づらいのかなぁと、勝手な想像を巡らせていたのですが、1か月を過ぎた今もまだ「0」のままなので、いい加減どうにかしないとと思いました。

「ピーーーーーーーーーーーーーー」(心停止状態)


クロールエラーはないか

Search Consoleの左メニューにある「クロール」のところをちゃんと見てみます。

まず先頭の「クロールエラー」。
「サイトエラー」と「URLエラー」の2項目ありますが、どちらの「過去90日間エラーが検出されませんでした」となっているので、大丈夫っぽいですね。

クロールの統計情報を確認

次に、「クロールの統計情報」を見てみます。
「過去90日間のGooglebotの活動」とあるので、グラフに動きがあるということは、クロールできてるっていうことなんでしょう。たぶん。。。
10月7日に3ページ、クロールされてるみたい。その後ぼちぼち


robots.txtを確認

Bloggerでブログを作ると、デフォルトのrobot.txtはこんな風になっているのです。

User-agent: Mediapartners-Google
Disallow:
User-agent: *
Disallow: /search
Allow: /

各項目の意味については、こちら(robots.txtの書き方と効果的な活用法)を見ました。
真ん中よりちょっと下くらいで各項目について説明してもらえました。
(追記:後日山田くんがちょっと書いてくれました robots.txtの書き方)

このブログは、複数人数でいろいろなテーマについて記事を書いていく感じなので、開発チームのみなさんには記事に「ラベル」を付けてもらうようにお願いをしています。
そうすると、ラベルごとに記事の一覧が見れて、便利だな~と思ったわけです。
(そういうワケだからみんなラベル付けてくれ~)

たとえば、Kさんが書いてくれている「リンク切れ」というラベルがついている記事の一覧はhttp://stpsysdev.blogspot.jp/search/label/リンク切れ
というURLで表示できるのですが、このデフォルトのrobot.txtだと、このラベル別の記事ページにはクローラーが入らないようになってしまってるっぽいのです。

なので、これは変えたほうがいいな!と思いまして、こちら(Bloggerのサイトマップとrobots.txtの設定方法)を参考にして、robot.txtをこんな風にしました。

User-agent:* 
Allow: /search/label/
Disallow: /*archive 
Sitemap: http://stpsysdev.blogspot.jp/feeds/posts/default?orderby=UPDATED
これでインデックス数も増えるんじゃないかなぁ。と、期待ですが、どうなんだろう。

サイトマップを確認

いつだったか忘れてしまったのですが、かの心停止がずっと続いているのが気になり始めたころに、サイトマップを追加しました。
なんと、Bloggerにはサイトマップを作成する機能が備わっているので(こちらを参照しました:Bloggerのサイトマップ(sitemap.xml)の自動作成)、それで作成したものを「Search Console」⇒「クロール」⇒「サイトマップ」⇒「サイトマップの追加/テスト」から追加しました。

サイトマップのコンテンツというグラフを見ると、10月12日から送信されているページが増えているので、きっとこの時期にやったのかもしれません。

もしかしたらやらなくても上がってきてたのかもしれませんが、送信できているみたいですし、その後もコンテンツが増えるたびに数字が伸びてるみたいなので、OKってことにし、、、、!!?

ん?ちょっとまって

青が「送信」、赤が「インデックスに登録済み」

「インデックスに登録済み」が25もある!?ど、どういうこと・・・・・・

だって「インデックスステータス」が心停止だから、「インデックスに登録済み」のページが0っていうことなんじゃないの・・・チガウノ・・・・?

ヨクワカリマセン




というようなかたちで、Search Console からクロールについての設定を見直してみたのですが、これで「インデックスステータス」が息を吹き返してくれるといいのですが、、しばらく様子を見てみたいと思います。

なにかお知恵を貸してくださる方!コメントをお願いいたします。

そもそも「インデックスステータス」ってナニモノなのかしら、、、





【後記】
Kさんの見やすい記事を見習って、画像を使ってみたり、htmlをいじいじしてみましたが、なんか変。もうあきらめです。
h2タグの場所が変なのかな?エディタと二刀流だとはちゃめちゃです。
h2要素の個数は検索順位に影響を与えるか?
次回もがんばります。カステラ食べたい。

2015年10月22日木曜日

タイニーPNG のAPIを利用した画像圧縮アプリケーションの作成

こんにちわ山田です。
昨日は、オリオン座流星群がよく見えたそうですね。
まったく見れなかったです、、。

たまたま夕方のニュースで情報を得ていたので、楽しみにしていたら
朝になるまで思い出せませんでした。

そんなこんなで、画像を外部のサービス(API)を利用して
圧縮して、画像サイズを小さくするメソッドを作成したので、その覚書です。

開発環境 ASP.NET
開発言語 C#

使用したのは、TinyPNGでほぼ公式のリファレンス通りに実装しました。 
画像→byte配列にするのが苦戦しました。ここを参考にさせていただきました。 

呼び出し元
    protected void ButtonUpload_Click(object sender, EventArgs e)
    {
        Label1.Text = "";
        if(FileUpload1.HasFile)
        {
            string path = @"C:\temp\\";
            //つけたいファイル名
            string fileName = FileUpload1.PostedFile.FileName;
            string output = Path.Combine (path, fileName);

            //アップロードファイルを入力ストリーム経由でbyte配列に読み込む
            Byte[] aryData = new Byte[FileUpload1.PostedFile.ContentLength];
            FileUpload1.PostedFile.InputStream.Read(aryData, 0, FileUpload1.PostedFile.ContentLength);
            output = SizeDownImage(aryData, output);
            Label1.Text = "次のファイル名で保存しました: " + output;
        }
  
呼び出される側
    /// <summary>
    /// アップされた画像をTinyJPGのAPIを使用して、圧縮して保存するメソッド
    /// ・引数:
    ///  byte[] 画像のバイナリデータ
    ///  string 保存先のファイルパス
    /// ・返り値:
    ///  string 保存後のファイルパス
    ///   ※失敗した場合は、空を返却
    /// </summary>
    /// <param name="_imageByte"></param>
    /// <param name="_output"></param>
    /// <returns></returns>
    public static string SizeDownImage(Byte[] _imageByte, string _output)
    {
        string key = [外部APIキー];

        string url = [外部APIのURL];
        string auth = Convert.ToBase64String(Encoding.UTF8.GetBytes("api:" + key));

        WebClient client = new WebClient();
        client.Headers.Add(HttpRequestHeader.Authorization, "Basic " + auth);
        string result = "";
        try
        {
            //画像アップロード //
            client.UploadData(url, _imageByte);
            // 画像ダウンロード
            client.DownloadFile(client.ResponseHeaders["Location"], _output);
            result = _output;
        }
        catch (WebException ex)
        {
            log.Error(ex.Message);
        }
        finally
        {
            client.Dispose();
        }
        return result;
    }
}

2015年10月20日火曜日

クエリの速度を見る方法



こんにちわ山田です。
MSのManagement Studio を使った SQL Server の操作で
クエリの実行速度の計測方法を知ったのでその覚書です。




いつも使っているクエリの実行の右隣に、
「実行プラン」と「クライアント統計」というアイコンがあります。
選択して、いつも通りクエリを実行すると、なんと!実行速度がさくっとでます!

外部結合をたくさんして、サーバーの負荷がかかっているのかなと心配になったら
ここの一番下の、「サーバー応答の待機時間」を見れば処理にかかった時間を見ることできます。

該当するページ内リンクを他のタブで全て開く方法

こんにちは!Sです!
今日はページ内リンクを一気に開く方法を調べていたので、その覚書と共有です。

下記のように書けばページロードした際にページ内リンクが一気に別タブで開きます。
しかしこの場合ヘッダーやフッダーなどのあらゆるリンクを開くのでページ数の多いサイトでは本当に恐ろしいことになります・・・

<script type="text/javascript">
<!--
window.onload = function () {
for (var i = 0; i < document.links.length; i++) {
var ele = document.links[i];
if (ele.href.match(/^http/)) {
window.open(ele);
}
}
}
function openwin() {
var url = this.href;
if (document.all && !window.opera) {
if (url.match(/[^\x21-\x7E]/)) {
if (!window.createPopup) {
this.target = "_blank"; // IE 5.5 未満は target="_blank" を適用して終了
return true;
}
url = escape(url); // 取得 URL をエスケープ
url = decodeURIComponent(url); // エスケープした文字列をデコード
url = encodeURI(url); // 正常な URI に URL エンコード
}
}
window.open(url);
return false;
}
</script>


その為何か特定のリンクだけを対象にする場合にはより具体的なURLを指定する必要があります。




「datepicker」を日本語化する

こんにちわ、開発者のⅠです。

前回紹介したdatepickerについて、各表記をデフォルトの”英語”から”日本語”に変更してみたいと思います。

それでは、datepickerの各プロパティに対して表示させたいもの(日本語)を設定してあげましょう。



/* 日本語化してみよう */

jQuery(function($){
    $.datepicker.regional ['ja'] = {
        closeText : '閉じる',
        prevText : '<前',
        nextText : '次>',
        currentText : '今日',
        monthNames : ['1月', '2月', '3月', '4月', '5月', '6月', 
        '7月', '8月', '9月', '10月', '11月', '12月'],
        monthNamesShort : ['1月', '2月', '3月', '4月', '5月', '6月', 
        '7月', '8月', '9月', '10月', '11月', '12月'],
        dayNames : ['日曜日', '月曜日', '火曜日', '水曜日', '木曜日', '金曜日', '土曜日'],
        dayNamesShort : ['日', '月', '火', '水', '木', '金', '土'],
        dayNamesMin : ['日', '月', '火', '水', '木', '金', '土'],
        dateFormat : 'yy/mm/dd',
        firstDay : 0,
        isRTL : false,
        showMonthAfterYear : true,
        yearSuffix: '年'};

    $.datepicker.setDefaults($.datepicker.regional['ja']);
});


これで、カレンダーの表記が日本語に変化しているはずです。
この他にも、日本語化対応だけではなく、特定の部分の表示・非表示を切り替えることもプロパティを指定することで可能です。

それでは、今回はここまでです。
次回、またお会いしましょう。








2015年10月19日月曜日

jQuery UI の「datepicker」とは?

こんにちわ、開発者のⅠです。
今回は、datepickerについてお話したいと思います。

このdatepickerは、カレンダーを表示させて日付を選択させるUIを実現するために用いるjQuery(Javascriptのライブラリ)の一つです。

まず利用するためには、j Query 本体を読み込む必要がありますが、自分のローカルに保存する必要はなく、以下の様にソースに直接書き込むことでインターネット経由で読み込むことが可能です。

<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.0.min.js"></script>


ただし、デフォルトの状態では年や月などの表記はすべて英語になってしまいます……。
デザインを変更するには、その設定を記述する必要が有りますが、その話はまた次回にしたいと思います。

それでは、また!

※参考ページ



グーグルアナリティクスで、好きなキャンペーンコードで集計する方法

こんにちは山田です。
グーグルのキャンペーンコードの設定方法を以前お話ししたのですが、
必要なURLが長すぎて私の場合、
使えないことがわかりました。

その対処方法として、目的のURLに対して、
決まった任意のキャンペーンコードをつけて書けるようにするのが目的です。

調べてみたらそこまで難しくなく以下の手順を書きます。
①目的のURLのクエリストリングに任意のパラメータを振ります。
www.sample.com/?trid=id201410

②グーグルアナリティクスを開き
行動→すべてのページ
右上の検索窓に、「trid=」と入れます

すると検索結果に、パラメータn値がid201410のものを一覧表示させることができます。


元々あるキャンペーン機能と違い、キャンペーン名を保持することができない点がありますが。
なんとか使えそうです。

ここを参考にしています。
http://sem-labo.net/blog/2009/08/24/0144/

2015年10月16日金曜日

インライン式 <%= %> と <%# %>の違い

インライン式
<%= %> と <%# %>の違い

こんにちわ、山田です。
ASP.NETを使っていてよくわからなかったところがあったのでまとめました。
この書き方、調べたらインライン式というらしい。
自分がよく使うものをまとめてみました。

■埋め込みコードブロック【<%= %>】
Response.Writeで代用できるブロック
値(string)を返す時はこれを使用する

(例)
<%= shopName %>
   ↑ソースファイル(csファイル)でprotectedのもの

■データバインド式【<%# %>】
RepeaterサーバーコントロールなどでBindしている場合(Eval)はこれを使う

(例)
 <asp:Repeater runat="server" ID="shopList">
  <ItemTemplate>
    <%# (Eval("ShopName"))%>
  </ItemTemplate>
 <asp:Repeater>


インライン式(<%=, <%@, <%#, <%$, <%--)の概要



jquery.lazyload.jsを使ってみた(画像の遅延読み込み)

こんにちは開発者のKです。

スマートフォンでWebページを閲覧する機会が増えた昨今、比較的貧弱な3G回線でもスムーズに閲覧できるように
サーバへのリクエスト数やダウンロードするリソースの容量はなるべく抑えたいですよね。

通常ページ容量の大半を占めるのは画像だと思いますので、その一つの解決策として画像の遅延読み込みを実装したjqueryのプラグイン「jquery.lazyload.js」を使ってみましたので所感を述べたいと思います。

遅延読み込みについて

通常ブラウザはHTMLを1行目から順に解析していき、imgタグやcssのbackgroudで指定された画像を発見した際、即時画像のダウンロードを開始します。
画像の遅延読み込みとは、この読み込みタイミングを遅延させ、ページを一度表示し終わった後に非同期でダウンロードしようというものです。
ブラウザの表示領域は限られていますから、表示領域の外にある画像は、あとから読み込んでも影響は少ないよね、という考え方です。
これにより、最初にページ読み込みが完了までのページ容量を削減し、表示速度の高速化が期待できます。


使い方

簡単な使い方は以下の通りです。
  1. jquery本体とlazyloadを読み込みます。
  2. 遅延読み込みさせたいimgタグにlazyクラスを付与します。このクラス名は任意に変更可能です。srcには仮で表示させる画像を指定しておき、data-originalに本来表示させる画像のURLを指定します。
  3. step2で付与したlazyクラスを持つ要素に対して、lazyloadを実行します。その際、様々なオプションを渡すことができます。










lazyloadのオプション

ソースを見ると、lazyloadには様々なオプションがありますが、公式ドキュメントなどでもあまり触れられていないので、紹介したいと思います。

threshold

thresholdで指定したピクセル数より下にある画像を読み込み対象とすることができます。
デフォルト値は0なので、描画領域に入った際に読み込み開始しますが、例えばスマートフォンで縦にスクロールしていくリストページを考えた時、640としておけば次の1スクロール分も事前に読み込んでおくことができます。

failure_limit

一度読み込み対象となったが、何らかの理由により読み込み完了していない画像を、何回まで再読み込みを試みるかを指定します。
コードを読んだだけで実際に試していないので、間違っていたらすみません。

event

読み込み対象を検知するイベントを指定します。デフォルトはscrollなので、ページスクロールの度に読み込み対象を再走査します。
ここにはカスタムイベントを指定することも可能で、例えばスワイプによるカルーセルUIを実装したプラグインと組み合わせて、スワイプの度に再走査をかけることも可能です。
※jqueryカスタムイベントの発火はtrigger('event_name')で行えます。

effect

遅延読み込み後に画像を表示する際の効果を指定します。デフォルトのshowはただ表示するだけですが、
fadeInとすると、アニメーションでリッチに表示することができます。

container

遅延読み込みを行う範囲を指定します。デフォルトはwindowオブジェクトなので、ページ全体となります。
特定のdivタグ内に限定したい場合などに使えると思います。

data-attribute

imgタグのdata属性の名前を変更できます。デフォルトはサンプルの通りdata-originalですが、他ライブラリとの名前の衝突などで変更したい場合に役立ちます。

skip_invisible

trueを指定すると、対象の画像が可視状態でない場合(display: noneなど)は読み込みがスキップされます。

appear

対象の画像が描画領域に入った際に(threshold含む)実行されるコールバックメソッドを登録できます。
第一引数には遅延読み込み前の要素数、第二引数にはオプション(lazyloadで渡したものとデフォルト値がマージされたもの)が渡されます。
一覧ページにおいて、画像以外にもtwitter, Facebookボタンの様な通信を要するウィジェットが実装されているケースがあるかと思います。
そんな時にページ表示時にまとめて初期化するのではなく、個別に初期化処理を走らせれば、より初回表示時のコストを削減できますね。
イメージ:
$('img.lazy').lazyload({
    appear: function (left, settings) {
        // ツイートボタンも遅延読み込み
        (typeof twttr !== 'undefined') && twttr.widgets.load();
    }
});

load

appearと似ており、対象の画像が読み込み完了した際に実行されるコールバックメソッドを登録できます。

placeholder

画像が遅延読み込みされるまでに表示する仮画像を指定します。
デフォルトではグレーの画像となっていますが、任意の画像に差し替えることができます。
元のimgタグのsrcに指定しても同じ挙動となります。


遅延読み込みはSEO的に良くない?

こんな記事がありました。
最近ではGoogleのクローラもJavascriptを実行できるようですが、遅延読み込みのトリガーの実装方法によっては、クローラに画像が認識してもらえないケースがあるとのことです。
ユーザの入力を起点(スクロール等)とする場合、クローラは再現できないようですね。

実際にFetch as Googleしてみて何かわかったらまた記事にしたいと思います。


2015年10月15日木曜日

Googleアナリティクスのカスタムキャンペーンとは

こんにちわ山田です。

グーグルアナリティクスにてアクセスの解析に欲しい機能がありました。
リファラーのない、広告やメルマガからの流入を測定する方法です。
調べてまとめてみました。
目的のURLのクエリストリングに計測パラメータを付けることにより実現します。

■グーグルから便利なURL生成ページがあります
https://support.google.com/analytics/answer/1033867?hl=ja


パラメータ 対応するディメンション 設定する項目 必須/オプション
utm_source 参照元 媒体名を指定 必須
utm_medium メディア 広告の種類を指定 必須
utm_campaign キャンペーン 広告のキャンペーン名を指定 必須
utm_term キーワード 広告のキーワードを指定 オプション
utm_content 広告のコンテンツ 広告の種別などを指定 オプション

パラメータは複数あり、上記の3つは必須です。
こんな感じのURLが生成されます。
http://stpsysdev.blogspot.jp/2015/10/google.html?utm_source=twitter&utm_medium=social&utm_campaign=campaign201510

パラメータに悩んだら、下の2個目のリンクがケーススタディ集にまとめてあるので必見です。


Google アナリティクスで広告からのアクセスを計測する方法


【まとめ】Googleアナリティクスのカスタムキャンペーンのケーススタディ

■作成したコードをGAから確認する方法

GAの
集客>キャンペーン>すべてのキャンペーン
と開いていけばアクセスしたセッション数がわかります。

私の場合は、複数のURLに同じキャンペーンコードを仕込むことを考えているので
さらに「ランディング ページ」の表示項目だしてあげてどのページが見られているか確認することができます。

2015年10月14日水曜日

知っておくと便利なURLスキーム

こんにちは山田です。

本日はブラウザから「地図を見るボタン」を選択した際に、地図アプリが立ち上がり、指定した位置を開く
という物を作っている時に気づいたことのお話しです。

URLスキーム?? という謎の言葉が何度が飛び交いました。
ということで調べてみました。

URLスキームとは?

たとえば↓のものです。
http://maps.apple.com/maps?q=渋谷駅

先頭は地図のアプリを開くことを指しており、
q命令らしく
q以降で命令の内容を指定しています。

つまり、地図のアプリケーションを起動⇒渋谷で検索

という流れになります。

参考までに詳しく乗っているリンク先に記載されている情報を転載させていただきます。めもめお、、、
表:「マップ」のURLスキームで使用できるおもなパラメーター

パラメーター     内容
q     検索キーワードを指定する(緯度/経度も指定可)
ll     緯度/経度をカンマ(,)区切りで指定する
spn     表示距離を指定する
t     表示モードを指定する(m:標準、k:航空写真、h:地図+写真)
z     表示サイズを指定する
saddr     経路検索用の出発地を指定する
daddr     経路検索用の目的地を指定する


iPhone/iPad標準「マップ」と「Google Maps」、どちらを選ぶべき?

知っておくとiPhoneをもっと便利に使える「URLスキーム」とは?

2015年10月13日火曜日

~正規表現を使って文字列を取得してみる~

始めまして、開発者のⅠです。
日々の開発で経験したことなど、色々と書かせていただきますので宜しくお願い致します。

さて、今回は正規表現を用いて文字列を取得する方法について書いてみたいと思います。
正規表現については、どこかで耳にしたことがあると思います。それをここで全て説明するのは難しいので省略いたしますが、一言でいうと「抽象的な文字列の表現」と言えます。

※参考URL:http://www.mnet.ne.jp/~nakama/

この正規表現を利用して、例文から条件と合致する文字列を取得してみたいと思います。
正規表現を使って日付と曜日を取得してみましょう。

-----------------------------------------------------------------------
string sentence = "2015年10月13日火曜日, 天気は晴れです, 今日の最高気温は24℃です ";

Regex regDate = new Regex("(2015).*(曜日)");
Match s_date = regDate.Match(sentence);
string test = (string) s_date.Value;
------------------------------------------------------------------------

これで、変数 test に「2015年10月13日火曜日」が入っていれば成功です!

今回はここまでです。

また次回、お会いしましょう。









2015年10月9日金曜日

SQL 算術オーバーフロー エラー

「expression をデータ型 datetime に変換中に、算術オーバーフロー エラーが発生しました。」

こんにちはYです。
クエリを実行中、上記のエラーが発生してちょっと調べてみました。


declare @datetimedisp datetime
set @datetimedisp = 20160101

select
    *
from
    mst_table
where
  1 = 1


どうやら、int型の20160101をdatetime型に暗黙的キャストをSQLServerが行っていたらしく、
キャストの失敗が原因でこのようなエラーが起きていたのだとわかりました。

正しくは 「2016-01-01」または「2016-01-01 00:00:00」と代入するのが正しいようです。
久しぶりに触って忘れていたことでした。

2015年10月7日水曜日

iOS9のATS絡みの審査とリジェクトについて

Zメンです。iOSの開発に関するあれこれを書いていきます。



■iOS9で出てきたATSってなに?


iOS9が出てから(っていうか出る前から)開発者の間でATS絡みの話題が結構出てますね。
ATS自体はいまさら感がありますが、結局審査の時どうなるの?というところが意外と触れられてないです。
ちなみにATSはAppTransportSecurityの略ですね。


簡単に言うと
「今後アプリでの通信は全てHTTPSが推奨ですから!」
「HTTPで通信しようとしたらHTTPSに強制変換しますから!!」
な話です。


これが結構曲者な感じで、
HTTPSといっても『あれね、SSLね』ではなくて、具体的には
 ○TLS バージョン 1.2 以上
 ○接続時に使用できる暗号スイートに制限がある
 ○サーバ証明書に制限がある
   ・SHA256 以上のフィンガープリント
   ・2048 ビット以上の RSA キー、もしくは 256 ビット以上のECCキー
   ・無効な証明書を使用した場合は強制的に失敗になり、接続できない
な条件があります。


なので使用しているサーバーの環境によってそもそも対応できないよ!てことが普通にあるかと。
運営しているサイトがでかければでかいほどこのへんの変更は時間かかりそうですね。



■ATSの暫定対応(非推奨)


先に公開されてる対応方法だけ書いておきます。
といってもいろんなところで既に書かれまくっているので
こことかここ
とか参考にしてもらったほうが早いです。
『iOS ATS』でわんさか出てきます。



■懸念点と審査・リジェクト


今回の仕様変更の影響範囲は通信全てなので、
NSURLConnectionAFNetworkingみたいなAPI通信以外にも
UIWebViewだとかWKWebViewのようなWEBページ表示もしっかり影響範囲です。



大手でもまだまだWebViewベースでアプリを作ってるところもあるなかで、
この仕様変更は結構きついなーと。

一応HTTPSで動作確認はしましたが、
 ・CDN使ってるとこ
 ・広告表示してるとこ・
 ・オーディエンスデータとってるとこ
などなどがほんとに動作保障しきれるのか?とかなり不安です。
一部通信エラーっぽいログとか出てたし。(ログはかなり不親切)


なので jQueryみたいなCDNのはまだいいとして、個々の広告業者なんかは
しらみつぶしに検証するとかほんと時間の無駄。


クックパッド開発者ブログ
さすがcookpadさん、この辺も言及されてますね。


で、本題のそもそもATSを無効にした場合、
とくにWebView使ってて NSAllowsArbitraryLoadsで設定を切らざるを得ない場合、
はたして審査は通過するのか、ということです。


このあたりは丁度審査中なので追って追記します。
2015.10.08 追記)
審査無事通過しました。
ドメインを個別に指定する方法でも、BOOL値切替でもどちらでも
今のところ審査には支障はないみたいです。



ちなみに、審査通ったからと言ってHTTPSとか考慮しないし、
という訳ではなく、iOSX?以降で必須にされる場合ももちろんあるだろうし、
Appleに対してすべての通信がSecureであるよ、とちゃんと伝える意味でも
早めにATSに準拠したかたちに修正するのが望ましいでしょうね。



参考)Apple Developer 公式ドキュメント


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サイトでは問題なさそうですが、ページごとの処理内容やサーバのスペックにもよるかと思いますので、
参考程度として頂けたらと思います。