このブログはURLが変更になりました

新しいブログはこちら→ https://matsuu.hatenablog.com/

Googleの検索結果リンクページはブラウザ毎に異なる

まずはこちらをご覧ください。
Google先生の検索結果リンクが予想以上に作り込まれていた件
一部引用

まとめ

  • (略)
  • Google先生の検索ページはhttpsでも遷移先のhttpページにRefererを送信しています。
  • 検索結果のリンクは302 FoundのRedirect処理をせずに、200 OKのhtmlを返します。
  • 200 OKのhtmlページでは本来の遷移先ページを読み込む処理が書かれていて、200 OKのURLから遷移したようにRefererを送信しています。ただしRefererの検索Queryパラメータのq=は予め削除されています。
  • (略)

なるほどー。
200 OKのページでwindow.location.replace()を使うことでブラウザのhistory遷移でも問題が出ないようにしてるのねと関心したのだが、実はブラウザごとに異なるとの情報を@dancerj先生から教えていただいた。

ほうほう。ということでいくつかのUserAgentを送ってみてレスポンスを確認してみたところ、以下の3種類を確認できた。

デフォルトの応答パターン

先のサイトでも紹介されているパターン。こちらの応答が確認できたのは、FirefoxChromeSafariiPhoneAndroid、IE11など。整形するとこんな感じ。

<script>
  window.googleJavaScriptRedirect = 1
</script>
<script>
  var m = {
    navigateTo: function(b, a, d) {
      if(b != a && b.google) {
        if(b.google.r) {
          b.google.r = 0;
          b.location.href = d;
          a.location.replace("about:blank");
        }
      }
      else {
        a.location.replace(d);
      }
    }
  };
  m.navigateTo(window.parent, window, "(リンク先URL)");
</script>
<noscript>
  <META http-equiv="refresh" content="0;URL='(リンク先URL)'">
</noscript>

window.parentを見てるのはiframeやframeset構造だった場合の対策だろうか。

Operaの応答パターン

OperaのUserAgentの場合以下のような応答になった。ふむ。

<script>
  window.googleJavaScriptRedirect = 1
</script>
<script>
  var m = {
    navigateTo: function(b, a, d) {
      if(b != a && b.google) {
        if(b.google.r) {
          b.google.r = 0;
          b.location.href = d;
          a.location.replace("about:blank");
          try{
            if(b && b.frames) {
              var e = b.document.getElementsByTagName("IFRAME");
              for(b = 0; b < e.length; ++b) {
                var c = e[b];
                if(c.contentWindow == a) {
                  c.parentNode.removeChild(c);
                  break
                }
              }
            }
          }
          catch(n) {
          }
        }
      }
      else{
        a.location.replace(d);
      }
    }
  };
  m.navigateTo(window.parent, window, "(リンク先URL)");
</script>
<noscript>
  <META http-equiv="refresh" content="0;URL='(リンク先URL)'">
</noscript>

window.parentが存在した場合の扱いがOperaは異なるということだろうか。

Internet Explorer 10以前の応答パターン

さてお待ちかねのIE様。IE6からIE10までは以下のような応答になっていた。ちなみにIE11は上のデフォルト。

<script>
  window.googleJavaScriptRedirect = 1
</script>
<body style="display: none">
  <a href="(リンク先URL)" id=link target=_parent>
    <textarea id="frm"></textarea>
</body>
<script>
  var m = {
    navigateTo: function(b ,a ,d) {
      if(b != a && b.google) {
        if(b.google.r) {
          b.google.r = 0;
          a.document.getElementById("link").click();
        }
      }
      else {
        try{
          var f = a.location.search.match(/[\?&]ccnt=([^&]*)/);
          if(f) {
            var g = f[1], h = a.sessionStorage, k = h.rds, l = h.rdcnt;
            "b" == k && l == g ?
                (
                  a.sessionStorage.rds = "f",
                  a.history.back(1)
                )
              :
                (
                  a.sessionStorage.rds = "b",
                  a.sessionStorage.rdcnt = g.substr(0,5),
                  a.document.getElementById("link").click()
                )
          }
          else
            a.location.search.match("[?&]frm=") ?
                a.setTimeout(
                  function() {
                    var b = a.document.getElementById("frm");
                    b.value ?
                        (
                          b.value = "",
                          a.history.back(1)
                        )
                      :
                        (
                          b.value="b",
                          a.document.getElementById("link").click()
                        )
                  }, 0
                )
              :
                a.document.getElementById("link").click()
        }
        catch(p) {
          a.document.getElementById("link").click()
        }
      }
    }
  };
  m.navigateTo(window.parent, window, "(リンク先URL)");
</script>
<noscript>
  <META http-equiv="refresh" content="0;URL='(リンク先URL)'">
</noscript>

おお、全然違う。なんだこれはよくわからん。誰か助けて下さい。

まとめ

大変ですね。とりあえずIE10以前は死んでくれ。