AWS Lambdaとは

Lambdaの読み方がわからない
⇒インスタンスベースの仮想サーバー(EC2、ElastiChache、Redshiftなど)を使わずにアプリケーションを開発するアーキテクチャ

>Lambda を使用すれば、実質どのようなタイプのアプリケーションやバックエンドサービスでも管理を必要とせずに実行できます。コードさえアップロードすれば、高可用性を実現しながらコードを実行およびスケーリングするために必要なことは、すべて Lambda により行われます。コードは、他の AWS サービスから自動的にトリガーするよう設定することも、ウェブやモバイルアプリケーションから直接呼び出すよう設定することもできます。

サーバー管理がないということは、sakuraの共有サーバーのようなものか?
これ、わざわざやる必要あるか?

とりあえず、AWS Lambda 入門を叩いてみましょう。

なんだこれは!? とりあえず、Qwiklabsにjoinしましょか。

By the end of this lab you will be able to:

  • Create an AWS Lambda function
  • Configure an Amazon S3 bucket as a Lambda Event Source
  • Trigger a Lambda function by uploading an object to Amazon S3
  • Monitor AWS Lambda S3 functions through Amazon CloudWatch Log

コンピューティングにlambdaがありますね。

node.jsのコードを実行します。

exports.handler = (event, context, callback) => {
    // 「Hello World!」という文字列で続行
    callback(null, 'Hello world!');
};

ec2でpythonにpost

[ec2-user@ip-xxx-xx-xx-xx app]$ python -V
Python 2.7.14

[ec2-user@ip-xxx-xx-xx-xx app]$ python35
Python 3.5.5 (default, Apr 25 2018, 23:51:32)
[GCC 4.8.5 20150623 (Red Hat 4.8.5-11)] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>>

python2系だからか?
usr/binを見ます。

うまくいきませんね。
他の方法を試してみましょうか。。

vagrantでajaxでpythonにpostする

index.php

<!DOCTYPE html>
<html lang="ja">
<head>
  <title>Ajax</title>
</head>

<body>
  <h1>Ajax</h1>
  <form id="form">
    <div><label>送信する数字</label><input type="number" id="number" value="0"></div>
    <div>
      <label>送信するテキスト</label>
      <textarea id="text"></textarea>
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
  </form>
  <div id="result"></div>

  <script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  <script type="text/javascript">
    $(document).ready(function(){
      $('#form').submit(function(){
        event.preventDefault();
        var $form = $(this);
        $.ajax({
          url:'http://localhost:8000/cgi-bin/index.py',
          type: 'post',
          dataType: 'text',
          data: {
            number: $('#number').val(),
            text: $('#text').val()
          },
        })
        .done(function(response){
          $('#result').html(response);
        })
        .fail(function(){
          $('#result').html('Failed.');
        });
      });
    });
    </script>
  </body>
</html>

index.py

#!/usr/bin/env python
# -*- coding: utf-8 -*-

import cgi, cgitb

cgitb.enable()

form = cgi.FieldStorage()
text = form.getFirst("text")
n = form.getFirst("number")
sequence_list = []

print('Content-type: text/html\nAccess-Control-Allow-Origin: *\n')
print("<p>送信された数字: {}</p>".format("None" if n is None else int(n)))
print("<p>送信されたテキスト: {}</p>".format(text))
python -m http.server --cgi

何故だ? 問題はHTML側ではないと思うので、AWSもしくはsakuraでやってみるか。

index.phpをindex.htmlに変更します。

192.168.35.1 – – [26/Aug/2018 10:19:03] code 403, message CGI script is not executable (‘/cgi-bin/index.py’)
192.168.35.1 – – [26/Aug/2018 10:19:03] “POST /cgi-bin/index.py HTTP/1.1” 403 –

なに?
[vagrant@localhost app]$ cd cgi-bin
[vagrant@localhost cgi-bin]$ chmod 755 index.py

192.168.35.1 – – [26/Aug/2018 10:23:35] “GET / HTTP/1.1” 200 –
192.168.35.1 – – [26/Aug/2018 10:23:43] “POST /cgi-bin/index.py HTTP/1.1” 200 –
: そのようなファイルやディレクトリはありません
192.168.35.1 – – [26/Aug/2018 10:23:43] CGI script exit status 0x7f00

う~ん、なんでだろう。
jsのdocument.titleで取得してphpファイルに送ることもできるが、後々のことを考えるとpythonでやりたいですね。

トラッキングcookieの仕組み

1. javascriptのタグからアクセスしてきたユーザーにcookieをsetする (例えばFXのページ)
2. 別のページをアクセスした場合に、1でsetしたcookieを読み込んで、1に関連する広告を配信する

< async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></ >
<!-- auction -->
< class="adsbygoogle"
     style="display:inline-block;width:728px;height:90px"
     data-ad-client="ca-pub-5909906903001543"
     data-ad-slot="6431329951"></ins>
< >
(adsbygoogle = window.adsbygoogle || []).push({});
< >

まず、広告を出しているページが何のページか理解できないといけない。
pythonで解析できるようにしたい。

titleはbeautiful soupで解析する。

import requests, bs4
res = requests.get('http://hpscript.com/blog/')
res.raise_for_status()
soup = bs4.BeautifulSoup(res.text, "html.parser")
print(soup.title)

[vagrant@localhost app]$ python3 index.py
ソフトウェアエンジニアの技術ブログ – ABCD: Always Be Coding and Design

1. javascriptからpython fileにurlをpostしたい。
2. titleをpythonで形態素分析したい。
いけるか?

adsenseが広告を表示している時のscriptタグを見てみよう

<html>
 <head>
 <script>var google_casm=[];</script></head>
  <body leftmargin="0" topmargin="0" marginwidth="0" marginheight="0">
   <script>var viewReq = new Array();function vu(u) {var i=new Image();i.src=u.replace("&amp;","&");viewReq.push(i);}</script>
    <script>
     vu("https://googleads.g.doubleclick.net/pagead/adview?ai\x3dCNObGSnmAW8HkMcy8qAGF6pToCea_s-9Nt8nw14wBwI23ARABIABgifvEhPQTggEXY2EtcHViLTU5MDk5MDY5MDMwMDE1NDPIAQmpAia1Lc4RUEM-qAMBqgSpAU_QQ_Rj93S8kVbtJKXBn61POdqV-PJKkq6oiRUHR8R3xXVht0iQFjq2o58McqzSOPki4ViMccrfpDxizihR5gxjXu1-qq_MV0AttoMAoplvpeafMKLu6MqIgOgSPwwDQYRIMg950_-ErWJUJtnkTTwEZDgLU0yKtgbmZ_L3nN2wnRHsyjF2sS2rI1ghh34IjMCyQPx-WEie9FZEpMgMbcfxEEtQVxM9IiSABu3ThJ-Hh8_FV6AGIagHpr4bqAfZyxuoB8_MG9gHANIIBQiAYRAB\x26sigh\x3d7lNTaw-j1Lg\x26tpd\x3dAGWhJmvGJR22zlwGWMoBY7QldpBR54WOoVfhFqBTgNjTnIeH4Q")</script><iframe id="a4fcaf81" name="a4fcaf81" src="https://ads.as.criteo.com/delivery/r/afr.php?did=5b80794a3ecfb6aec32279adbb7dc500&amp;z=W4B5SgAMckEKKh5MAAU1BeHMADN-sy159r8etg&amp;u=%7Cbqp5UtXU%2FozCsXrUntRD9aG8mBTS%2F4cMmUHa%2B7P%2FHbI%3D%7C&amp;c1=R15UMXQIVgOy1yFtMk-OzIVKTl7RHrqjv9VEgFn2s5CInTakLjEscWAT_QgGCs-DVac46ma0roVknAcVeiz79qA2jvRycM3wXHRt_ZC6ggqQ7Z8L8VBfDIlxb-1KofGAcbIdMvKaVCvd8efl34JCyEjMZxDTgFk_N0MyDRJuY1LLIrBq-p4utMNjs8LwhgBCqJwMYbJazdskLfTa2B_s6EavaaQFpSC8mfGIpS6WwfMZ-H6B0zAnYFMg5Y3_cNZ3ReFwFysqbLPncHVSha5lNVpM6gv1VwpGthJmOiC2HGBPtHfgld82edQj06OnpmsFFgExvKn1Xy9Sf4Rocj4-xoo9dE9mi_dAE-f2Px4BVMk67ET0YpkcRNq6DoXmez5UNfI0nF2OonkbauC-lIvdHnVnbkCeXh3J&amp;ct0=https://adclick.g.doubleclick.net/aclk%3Fsa%3DL%26ai%3DCNObGSnmAW8HkMcy8qAGF6pToCea_s-9Nt8nw14wBwI23ARABIABgifvEhPQTggEXY2EtcHViLTU5MDk5MDY5MDMwMDE1NDPIAQmpAia1Lc4RUEM-qAMBqgSpAU_QQ_Rj93S8kVbtJKXBn61POdqV-PJKkq6oiRUHR8R3xXVht0iQFjq2o58McqzSOPki4ViMccrfpDxizihR5gxjXu1-qq_MV0AttoMAoplvpeafMKLu6MqIgOgSPwwDQYRIMg950_-ErWJUJtnkTTwEZDgLU0yKtgbmZ_L3nN2wnRHsyjF2sS2rI1ghh34IjMCyQPx-WEie9FZEpMgMbcfxEEtQVxM9IiSABu3ThJ-Hh8_FV6AGIagHpr4bqAfZyxuoB8_MG9gHANIIBQiAYRAB%26num%3D1%26sig%3DAOD64_3_vbq_qdR_XCHngAs7zLB1xkG4oA%26client%3Dca-pub-5909906903001543%26adurl%3D" framespacing="0" frameborder="no" scrolling="no" width="160" height="600"></iframe><script src="https://tpc.googlesyndication.com/pagead/js/r20180820/r20110914/client/ext/m_window_focus_non_hydra.js" async="">
</script>

<script>function initWindowFocus() {window['window_focus_for_click'] =wfocusnhinit("https://googleads.g.doubleclick.net/pagead/conversion/?ai\x3dCNObGSnmAW8HkMcy8qAGF6pToCea_s-9Nt8nw14wBwI23ARABIABgifvEhPQTggEXY2EtcHViLTU5MDk5MDY5MDMwMDE1NDPIAQmpAia1Lc4RUEM-qAMBqgSpAU_QQ_Rj93S8kVbtJKXBn61POdqV-PJKkq6oiRUHR8R3xXVht0iQFjq2o58McqzSOPki4ViMccrfpDxizihR5gxjXu1-qq_MV0AttoMAoplvpeafMKLu6MqIgOgSPwwDQYRIMg950_-ErWJUJtnkTTwEZDgLU0yKtgbmZ_L3nN2wnRHsyjF2sS2rI1ghh34IjMCyQPx-WEie9FZEpMgMbcfxEEtQVxM9IiSABu3ThJ-Hh8_FV6AGIagHpr4bqAfZyxuoB8_MG9gHANIIBQiAYRAB\x26sigh\x3dAqdxowVUmv4","SnmAW6alMYaUigbcyq-gDw","CMGxl9bRht0CFUweKgodBTUFnQ",true,false);}if (window.wfocusnhinit) {initWindowFocus();} else {window['google_wf_async'] = initWindowFocus;}</script><script src="https://tpc.googlesyndication.com/pagead/js/r20180820/r20110914/activeview/osd_listener.js"></script><script type="text/javascript">osdlfm(-1,'','B669ySnmAW8HkMcy8qAGF6pToCQC3yfDXjAEAABABOAHIAQmgBiHSCAUIgGEQAQ','',1373412883,true,'xza\x3d1\x26mza\x3d1\x26ud\x3d1\x26la\x3d0\x26alp\x3dai\x26alh\x3d1235097137\x26',3,'CAASFeRodzIus_dBieBQD7HnIWF19lQiig','//pagead2.googlesyndication.com/activeview?avi\x3dB669ySnmAW8HkMcy8qAGF6pToCQC3yfDXjAEAABABOAHIAQmgBiHSCAUIgGEQAQ\x26cid\x3dCAASFeRodzIus_dBieBQD7HnIWF19lQiig','');</script><script src="https://tpc.googlesyndication.com/pagead/js/r20180820/r20110914/client/ext/m_qs_click_protection.js"></script><script>googqscp.init([[[[null,500,99,2,8,null,null,null,1]]],null,null,null,null,null,null,null,0]);</script><div style="display: none; position: absolute; z-index: 2147483647; width: 100%; height: 100%; top: 0px; left: 0px;"></div>

<img src="//www.google.com/ads/measurement/l?ebcid=ALh7CaRtfTX0i5pM-7NJdmInBZxQR_2XDJrER0DNwCrJ2CCr6n_HdcvqI2qqpMqL9NX0xgsG7QDylH6rGfso5mpyifDJm2tnlA" style="display:none;"><img src="https://googleads.g.doubleclick.net/pagead/ide_cookie" style="display:none;"><script>if (window.top && window.top.postMessage) {window.top.postMessage('{"googMsgType":"adpnt"}','*');}</script><div style="display:none" data-google-query-id="CMGxl9bRht0CFUweKgodBTUFnQ"></div><div style="bottom:0;right:0;width:86px;height:250px;background:initial !important;position:absolute !important;max-width:100% !important;max-height:100% !important;pointer-events:none !important;image-rendering:pixelated !important;z-index:2147483647;background-image:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAWBAMAAACrl3iAAAAABlBMVEUAAAD+AciWmZzWAAAAAnRSTlMAApidrBQAAAB8SURBVBjTbZEBDsAgCAOPH/T/r11EKGrGiBtZwbPCf8QOYn27AuVfrdRUqSCfwFWKpFypt061e1qN12O2SeIicUgPN00SzOy9eYqdJG5NtbTUA98HJrx/tcFJom5eMaTRbt7nsoXJ7+0H+3YQGYvXu+DxrP3eedxlga/4ACLHBaIDKh93AAAAAElFTkSuQmCC') !important">
  </div>
 </body>
</html>

まず、var google_casm=[];で google_casmを宣言しています。
leftmargin=”0″ topmargin=”0″ marginwidth=”0″ marginheight=”0″ なので、marginは0です。
var viewReq = new Array();function vu(u) {var i=new Image();i.src=u.replace(“&”,”&”);viewReq.push(i); で、viewReqの配列を宣言し、vu(u)でuの&ampを&に変換、viewReqに new Imageをpushしています。

でました、doubleclick.net ここでもかよ!
double clickはGAのcookieやsessionを保存しているDBなので、恐らくdouble clickにデータを読みに行っていると考えられます。
https://googleads.g.doubleclick.net/pagead/adview?ai

続いてiframe ここで広告を標示していますね。criteo.com?? 初めて聞きました。phpファイルですね。
iframe id=”a4fcaf81″ name=”a4fcaf81″ src=”https://ads.as.criteo.com/delivery/r/afr.php

criteoのサイトを見ると広告系のように見える。
https://www.criteo.com/

次はclick時の処理か?
function initWindowFocus() {window[‘window_focus_for_click’] =wfocusnhinit(“https://googleads.g.doubleclick.net/pagead/conversion/?

https://tpc.googlesyndication.com/pagead/js/r20180820/r20110914/activeview/osd_listener.js

pagead2.googlesyndication.com/activeview
//www.google.com/ads/measurement/l

まとめると、行動履歴のデータを読み込んで、iframeで広告を表示して、さらにどの広告をクリックしたか計測してDBに入ている、ということか。

簡易的に作るとすれば、
1. ユーザーのリファラーを取得する
2. リファラーから、ユーザーが見たページのコンテンツを言語解析する
3. 解析したコンテンツと近い広告をiframeで表示する

-> ユーザーのリファラーの取得は、cookieやsessionを埋め込んでればokだが、そうでない場合にどうするか?
-> DOM構造からどうやって言語解析をするか。形態素解析で頻出単語を抽出し、ページのカテゴリーを推測するか
-> adsenseの出稿管理画面ではどうなっているか?
-> DBで登録した広告をどうやってiframeで表示させるか?

仮説ではこんなところ。

adsenseのタグの中身を解析しよう

まず、アドセンスのタグの中身を見ていきます。adsbygoogle.jsを読み込んでますね。

script async src="//pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"
<!-- ddd -->
<ins class="adsbygoogle"
     style="display:block"
     data-ad-client="ca-pub-5909906903001543"
     data-ad-slot="8015520319"
     data-ad-format="auto"></ins>
script
(adsbygoogle = window.adsbygoogle || []).push({});
script

insタグの中身↓
class=”adsbygoogle”
style=”display:block”
data-ad-client=”ca-pub-5909906903001543″
data-ad-slot=”8015520319″
data-ad-format=”auto”

はInsertの略で、で囲まれた部分が後から追加された部分
ad-clientとad-slotがユニークな値のようです。

adsbygoogle.jsの中身をみていきましょう

ああああああああああああああああああああああああああああああああああああああああ

AWS https通信で位置情報を取得する

AWSに入ります。

__| __|_ )
_| ( / Amazon Linux AMI
___|\___|___|

https://aws.amazon.com/amazon-linux-ami/2018.03-release-notes/
21 package(s) needed for security, out of 31 available
Run “sudo yum update” to apply all updates.

cyberduckでも入ります。

index.phpをつくります。

<!DOCTYPE html>
<html lang="ja">
<head>
  <meta charset="utf-8">
  <title>位置情報取得サンプル</title>

  <script>
    // Geolocation APIに対応している
    if (navigator.geolocation) {
      alert("この端末では位置情報が取得できます");
    // Geolocation APIに対応していない
    } else {
      alert("この端末では位置情報が取得できません");
    }

    // 現在地取得処理
    function getPosition() {
      // 現在地を取得
      navigator.geolocation.getCurrentPosition(
        // 取得成功した場合
        function(position) {
            alert("緯度:"+position.coords.latitude+",経度"+position.coords.longitude);
        },
        // 取得失敗した場合
        function(error) {
          switch(error.code) {
            case 1: //PERMISSION_DENIED
              alert("位置情報の利用が許可されていません");
              break;
            case 2: //POSITION_UNAVAILABLE
              alert("現在位置が取得できませんでした");
              break;
            case 3: //TIMEOUT
              alert("タイムアウトになりました");
              break;
            default:
              alert("その他のエラー(エラーコード:"+error.code+")");
              break;
          }
        }
      );
    }
  </script>
</head>
<body>
  <h1>位置情報取得サンプル</h1>
  <button onclick="getPosition();">位置情報を取得する</button>
</body>
</html>


wow, 緯度経度が取れました。※渋谷にいます。
httpsならいけるんですね。
リダイレクトで取得するとすると、地域はやはりipアドレス + geo liteでしょうね。
問題は年齢、性別をどのように取得するか。
まずは、アドセンスの仕組み解析からでしょうか。
アドセンス、ASPのタグの中身を見ていきましょう。

AWS ELB(ロードバランサ)を設定していく

ロードバランサーの種類の選択で、3種類ありますね。
1. Application Load Balancer
2. Network Load Balancer
3. Classic Load Balancer

TCPとは? ->IPと同様にインターネットにおいて標準的に利用されている プロトコルです。TCPは、IPの上位プロトコルでトランスポート層で動作するプロトコル。

HTTPSを選択します。

きた~~~~~~~~~~~~~~~!!!!!!!!!!!!!!!!!!!
きゃ~ わ~い、わ~い。 これは嬉しいぞ。

azureも簡単だったが、AWSも簡単だ! これは凄い!
httpsが開通したので、早速javascriptの位置情報取得を試したいですね。

AWS Certificate Manager

コンソールにログインし、Certificate Managerへ行きます。

証明書のプロビジョニング を押下します。
>お客様のサイトの名前を指定し、ID を設定してください。残りの手順は ACM が行います。ACM は Amazon またはお客様のプライベート認証機関が発行する SSL/TLS 証明書の更新を管理します。

ACMは、SSL/TLS証明書を管理すると記載があります。ACMってなんかヨーロッパのサッカーチーム名のようですね。
すると、

証明書のリクエストページに遷移します。
>新しい証明書をリクエストするのではなく既存の証明書をインポートするには、[証明書のインポート] を選択します。
>パブリック証明書のリクエスト
> プライベート証明書のリクエスト

Amazonからリクエストするので、パブリック証明書のリクエストでいいのかな。

ドメイン名の入力画面になります。

Route53で設定したドメインを入力していくと、

あれ、検証保留中だ。
あ、発行済みになりました。大体2~3分です。

Route 53のhosted zoneで、ドメインに、CNAMEが追加されていればOKです。