読者です 読者をやめる 読者になる 読者になる

akiyoko blog

akiyoko の IT技術系ブログです

ゼロからはじめる Amazon QuickSight(AWS でお手軽データ分析 その3/3)

AWS QuickSight 統計解析

前々回の記事 および 前回の記事 で、Scrapy で Webスクレイピングしたデータを CSVファイルとして S3 に格納し、Amazon Athena のテーブルを作成して CSV のデータを流し込むところまでを実施しました。

今回は、作成した Amazon Athena のテーブルをデータソースとして Amazon QuickSight のデータ分析用のストアに取り込み、ダッシュボードからグラフを作成してみたいと思います。


<過去記事>
akiyoko.hatenablog.jp

akiyoko.hatenablog.jp


 

Amazon QuickSight とは

Amazon QuickSight については、昨年末の AWS Black Belt Online Seminar の資料に詳しく説明がされています。


要約すると、Amazon QuickSight は

  • すぐに利用可能(セットアップ不要)
  • フルマネージド
  • 多様なデータソースが使える
  • 低コスト
  • 結果のグラフはスマホにも最適化

という特徴を持つクラウドベースの BI ツールです。Redshift、RDS、Aurora、Athena、S3 などを始めとする AWS 上のデータセットをデータソースとして取り込んで、ダッシュボード上で様々なグラフ(*1)でデータを可視化することができます。CSVファイルや Excelファイルを QuickSight に直接アップロードしたり、オンプレミスサーバ上のデータベースをデータソースとして利用することもできるようですが、AWS のプロダクトと連携して利用するのがメインのユースケースとなるでしょう。

なお現時点では、N. Virginia、Oregon、Ireland の 3リージョンでしか利用できないようです。

「SPICE」というキーワードがちょくちょく出てきますが、独自に開発したインメモリデータストア用の超高速エンジンで、「Super-fast, Parallel, In-Memory Calculation Engine」の略だそうです。使用料は、その SPICEの容量(最初の1GBは無料)とユーザ数(最初の1ユーザは無料)に対して課金されます。お試しで使うのであれば、無料の範囲で十分使えそうです。

(参考)Amazon QuickSight | Editions


概要レベルの資料では、
Amazon QuickSight:【概要】Amazon QuickSightとは何か? | Developers.IO
も有用です。

あと、全然読み切れてませんが、クラスメソッドの しんや 氏の「Amazon QuickSight (全部俺) Advent Calendar 2016 - Qiita」なんていう資料もありました。猛者です。




 

目的

「AWS でお手軽データ分析」の全体像は、下図のように Scrapy → Amazon S3 → Amazon Athena → Amazon QuickSight という流れで AWS のいろいろなサービスを使ってデータ分析をすることを想定していますが、最終回である今回は、作成した Amazon Athena のテーブルを Amazon QuickSight のデータ分析用のストアに読み込んで可視化するところを試してみます。

f:id:akiyoko:20170311224916p:plain



 

QuickSight を使ってみる

QuickSight アカウントの作成

AWS Management Consle のアカウントとは別に、QuickSight アカウントを作成する必要があります。

QuickSight のアカウントについては「Amazon QuickSight: ユーザー管理やパーミッション設定について | Developers.IO」が詳しいです。


AWS Management Console にログインし、サービス一覧から「QuickSight」を選択します。
f:id:akiyoko:20170312115142p:plain

https://quicksight.aws.amazon.com/
にリダイレクトされますが、まだサインアップしていないので入れません。
ここでログアウトせずに続けて「Sign up」することで、現在 AWS Management Console にログインしているアカウントを QuickSight アカウントとして紐付けることができるようです。
f:id:akiyoko:20170312115205p:plain

「Standard edition」を選択します。最初の1ユーザーは無料です。
f:id:akiyoko:20170312115223p:plain

以下の内容を設定します。

QuickSight account name 任意(全体でユニークになるように)
Notification email address 任意
QuickSight capacity region US East (N.Virginia)


またここで、QuickSight からアクセスするリソースに対してパーミッションを与える必要があります。 *2

今回の例では、

  • Amazon Athena
  • Amazon S3(Athena のテーブルが参照している S3 バケット)

を許可する必要があります。

ということで、「Choose S3 buckets」をクリックします。
f:id:akiyoko:20170312115242p:plain

Athena のテーブルが参照している S3 バケット(今回の例では「marketstat」)を指定します。
f:id:akiyoko:20170312115306p:plain

アカウント作成を完了します。
f:id:akiyoko:20170312115324p:plain

f:id:akiyoko:20170312115347p:plain

グラフ(Visual)の作成

QuickSight のトップ画面はこんな感じです。

「New Analysis」をクリック。
f:id:akiyoko:20170312115409p:plain

「New data set」をクリックします。
f:id:akiyoko:20170312115429p:plain

取り込むデータセットとして、「Athena」を選択します。
f:id:akiyoko:20170312115505p:plain

データソース名を任意に設定します。
f:id:akiyoko:20170312115540p:plain

データを取り込む対象となる Athena のデータベースとテーブルを選択します。
f:id:akiyoko:20170312115611p:plain

インポート先に「SPICE」を選択して、「Visualize」をクリックします。
f:id:akiyoko:20170312115647p:plain

データの取り込みが完了すると、「Import complete」と表示されます。
f:id:akiyoko:20170312115748p:plain

ここから、グラフを作成していきます。
まず、グラフのタイプを選んで、X軸とY軸を選択します。
f:id:akiyoko:20170312115822p:plain

X軸をソートするには、以下のように操作します。
f:id:akiyoko:20170312115859p:plain

次に、フィルタ(データの抽出条件)を設定します。
f:id:akiyoko:20170312115934p:plain

左上の「Add」をクリックすると、グラフを「Visual」として保存することができます。
f:id:akiyoko:20170312120048p:plain


また、複数のグラフをダッシュボードとして保存して他のユーザと共有することができるほか、複数のグラフをプレゼン資料のようにまとめたものを「Story」として保存することもできます。



  

まとめ

今回、Scrapy → Amazon S3 → Amazon Athena → Amazon QuickSight という流れで AWS のいろいろなサービスを使って Webスクレイピングしたデータを可視化して分析するまでを、「AWS でお手軽データ分析」と称して三回に分けて記事にまとめてみました。

f:id:akiyoko:20170311224916p:plain


途中何度か軽く躓きかけたものの、全体的にはすんなりとクラウドベースでデータ分析する入り口までたどり着くことができました。
今後は、スクレイピングしたデータやダウンロードした公式のデータを使って、いろいろな分析を実際にしていきたいと思います。

*1:利用できるグラフの種類については、「利用可能な表示形式一覧 #quicksight #01 | Amazon QuickSight Advent Calendar 2016 | Developers.IO」を参照

*2:ここでパーミッションを設定しなくても、後で[Manage QuickSight] > [Account settings]から設定を変更することもできます。

ゼロからはじめる Amazon Athena(AWS でお手軽データ分析 その2/3)

AWS 統計解析

前回の記事 で、Scrapy で Webスクレイピングしたデータを CSV形式で S3 に格納しました。

今回は、S3 に格納した CSVファイルに対して、Amazon Athena を使ってデータ分析用のテーブルに取り込みたいと思います。


<過去記事>
akiyoko.hatenablog.jp



Amazon Athena とは

Amazon Athena については、先日開催された AWS Black Belt Online Seminar の「Amazon Athena」回の資料が詳しいです。


Athena は OLAP(OnLine Analytical Processing)ツールとして簡単な分析向けには使えるが、ETL(Extract, Transform, Load)用途としては向かないとのこと。ただし、大規模でないデータに対して、低頻度で ETL 処理をするユースケースには使えるとのことです。

  • 高速な分散クエリエンジン「Presto」を使用
    • インメモリで処理するので、バッチ処理ではなくてインタラクティブ向け
  • データをフルスキャン&変換する用途で使うと高コストになるので、バッチ処理には向かない
    • 大規模データに対してフルスキャンを定期的に行いたいなら、EMR を使う
    • サブクエリや JOIN を駆使した複雑な主計や高頻度なレポーティングをしたいなら、Redshift を使う

アクセス手段は Amazon Management Console、JDBLドライバ経由のみ。API や CLI は未提供とのことです。JDBC 経由で直接クエリを投げられるので、自前の BIツールとかも使えるようですね。

料金はクエリ単位の従量課金で、S3 のデータスキャンに対して「$5/1TB」で課金されます。注意点としては、

  • リージョンをまたぐ場合は、データ転送時間と転送料金が掛かる
  • パーティションをうまく設定するとスキャンするデータ量を効果的に減らすことができる

などが挙げられていました。

なお、Athena はディレクトリを指定して検索するので、バケット直下に直接ファイルを置くのは間違いとのことです。

 

目的

「AWS でお手軽データ分析」の全体像は、下図のように Scrapy → Amazon S3 → Amazon Athena → Amazon QuickSight という流れで AWS のいろいろなサービスを使ってデータ分析をすることを想定していますが、今回は、S3 に格納された CSVファイルを Amazon Athena のテーブルに流し込むところまでを試してみます。

f:id:akiyoko:20170311224916p:plain



取り込むデータの考慮点

Amazon Athena は CSV、JSON、ORC、Avro、Parquet などの形式のデータを取り込むことができます。

(参考)よくある質問 - Amazon Athena | AWS


今回は、S3上の CSVデータを取り込むことを想定していますが、その際に考慮しなければいけない点がいくつかありました。

CSVデータの内容

1)カンマを取り除く

CSVデータの値として、例えば「18,900」のようにデータの途中に半角カンマ(,)が存在する場合は、最初に出現したカンマの位置までで切られてしまい、値が「18」と認識されてしまうので、データの値から半角カンマ(,)を取り除いておく必要があります。

(参考)Remove comma from value · akiyoko/marketstat@82abc4b · GitHub


2)ヘッダ行

回避策があるかもしれませんが、Athena で を取り込んだ際に、CSV のヘッダ行も1データとして取り込まれてしまうという問題があります。
今のところ解決策が無いので、次の(QuickSight での)分析フェーズでデータをフィルタリングして除去するようにしています。

パーティション

Athena を利用する際は、「パーティション」という概念が非常に重要になります。

(参考)Amazon Athenaのパーティションを理解する #reinvent | Developers.IO


例えば、S3 に保存する際のディレクトリを以下のような形式にすることで、Athena でデータを取り込む際に、「year」「month」というパーティションが使えるようになります。

marketstat(バケット)
└── boj
    ├── year=2014
    ├── year=2015
    ├── year=2016
    └── year=2017
        ├── month=01
        ├── month=02
        └── month=03
            ├── 170301.csv
            ├── 170302.csv
            ├── 170303.csv
            ・
            ・


Amazon Athena はスキャンしたデータ量に対して課金されるため、頻繁に絞り込むカラムをパーティションのキーに指定することで、読み込むデータ量を効果的に減らすことができます。パーティションに設定した項目は、SQL の WHERE句の条件に指定して絞り込むことができます。





 

テーブルを作成

いよいよ Amazon Athena の実践です。

AWS Management Console のサービス一覧から「Amazon Athena」を選択します。
f:id:akiyoko:20170311165842p:plain

現在のところ、Amaozn Athena は「N. Virginia」「Ohio」「Oregon」の3つのリージョンしか対応していません。 *1

今回は「N. Virginia」を選択します。
f:id:akiyoko:20170311165926p:plain


f:id:akiyoko:20170311170013p:plain


「Query Editor」で「Add table」をクリックして、ウィザードを使ってテーブルを作成していきます。

f:id:akiyoko:20170311170030p:plain

項目 設定値
Database: marketstat(任意)
Table Name: boj(任意)
Location of Input Data Set: s3://marketstat/boj/

なお、S3 のロケーションは、スラッシュ(/)で終了する文字列でなければいけません。

f:id:akiyoko:20170311170127p:plain


データフォーマットに「CSV」を選択します。
f:id:akiyoko:20170311170203p:plain


CSV のカラム名とタイプを一つ一つ入力していくのは面倒なので、「Bulk add columns」で一括設定します。
f:id:akiyoko:20170311170321p:plain

今回は、

date int, expected_value int, preliminary_value int, name string, confirmed_value int

と設定します。

注意点としては、CSVファイルに出力された順番にカラム名を書かないといけません。なおパーティションに含めるフィールドは、ここには含めなくてよいです。
f:id:akiyoko:20170311195617p:plain

f:id:akiyoko:20170311170441p:plain


最後にパーティションを設定します。
f:id:akiyoko:20170311170617p:plain

パーティションは、

カラム名 タイプ
year int
month int

としました。タイプを「int」形式にしないと WHERE 句で「 > 」などの演算子が使えないため、上記のように設定しました。
f:id:akiyoko:20170311170657p:plain


エラーが出なければ、テーブル作成は完了です。

ちなみに、今回作成したテーブルの DDL は以下のようになっています。

CREATE EXTERNAL TABLE IF NOT EXISTS marketstat.boj (
  `date` int,
  `expected_value` int,
  `preliminary_value` int,
  `name` string,
  `confirmed_value` int 
) PARTITIONED BY (
  year int,
  month int 
)
ROW FORMAT SERDE 'org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe'
WITH SERDEPROPERTIES (
  'serialization.format' = ',',
  'field.delim' = ','
) LOCATION 's3://marketstat/boj/';



パーティションを使用した場合は、最後に

MSCK REPAIR TABLE marketstat.boj;

を忘れずに実行しなければいけません。 非常に重要です!!!

f:id:akiyoko:20170311170758p:plain



 

テスト

Amazon Athena は内部で分散処理基盤「Presto」を使用していて、標準の ANSI SQL が利用できます。

以下のSQLを実行してみます。

SELECT * FROM boj WHERE year = 2016 AND month BETWEEN 1 AND 3 limit 100;

f:id:akiyoko:20170311200800p:plain

WHERE句でパーティションを指定しているのがポイントです。これにより、スキャンする容量を節約することができます。


例えば、全検索するとスキャン量が「1MB」だったのが・・

f:id:akiyoko:20170314204257p:plain

WHERE句の条件として「year = 2016」を指定すると、「360 KB」ほどにスキャン量が削減されているのが分かります。

f:id:akiyoko:20170314204625p:plain



結果一覧の右上のファイルアイコンをクリックすることで、結果のCSVをダウンロードすることもできます。

f:id:akiyoko:20170311200817p:plain

"date","expected_value","preliminary_value","name","confirmed_value","year","month"
,,,"name",,"2016","2"
"160210",,,"",,"2016","2"
"160210","-400","-400","銀行券要因",,"2016","2"
"160210","-28800","-29900","財政等要因",,"2016","2"
"160210","-29200","-30300","資金過不足",,"2016","2"
"160210",,," ",,"2016","2"
"160210",,," ",,"2016","2"
    ・
    ・


 

まとめ

知識ゼロから Amazon Athena を使って、S3 に格納した CSVファイルを元にデータ分析用のテーブルを作成してみました。

少し難解だったのはパーティションの概念でしたが、それが理解できればあとは直感で何とかなりそうな感じでした。

次は、QuickSight を使って実際にデータ分析していきたいと考えています。

ゼロからはじめる Scrapy(AWS でお手軽データ分析 その1/3)

Python Scrapy AWS 統計解析

Python で Web クローリング・スクレイピングするためのツールといえば、 今や Scrapy が真っ先に候補に上がりますよね。


などを見ると、Beautiful Soup4pyquery も有力候補に見えますが、Google Trends を見てみるとやはり「Scrapy」が一番人気っぽいです。







目的

最終的には下図のように、Scrapy → Amazon S3 → Amazon Athena → Amazon QuickSight という流れで、AWS のいろいろなサービスを使ってお手軽データ分析をしてみたいと考えています。

f:id:akiyoko:20170311224916p:plain

今回は以下のように、Scrapy で Web スクレイピングして作成した CSVファイルを、S3 に格納するところまでを試してみます。

f:id:akiyoko:20170311224711p:plain:w400



まずは試しに、

http://www3.boj.or.jp/market/jp/stat/jx170301.htm
f:id:akiyoko:20170304235233p:plain

をスクレイピングしてみます。


 

事前準備

Mac に Scrapy をインストールします。

使用している Python は 2系ですが、Scrapy 1.1 以降は Python 3 対応済み(ただし Windows はサポート外)なので、3系でも特に変わりはないはずです。

前提条件

ローカル環境は以下の通りです。

  • MacOS Sierra 10.12.3
  • Python 2.7.12 (Anaconda 4.2.0)

インストール

pip でインストールします。

$ pip install scrapy

Scrapy (1.3.3)


 

プロジェクト作成

ひな形を作成

scrapy startproject コマンドを実行して、プロジェクトのひな形を作成します。

$ cd ~/PycharmProjects
$ scrapy startproject marketstat
$ cd marketstat

$ tree
.
├── marketstat
│   ├── __init__.py
│   ├── items.py
│   ├── middlewares.py
│   ├── pipelines.py
│   ├── settings.py
│   └── spiders
│       └── __init__.py
└── scrapy.cfg


 

Item を作成

まずはじめに、ひな形として作成された items.py を修正していきます。
Item クラスは、スクレイピングしたデータを入れるための箱になります。

以下のようなデータ項目を作成することにします。

項目名 変数名
日付 date
項目 name
予想値 expected_value
速報値 preliminary_value
確報値 confirmed_value


marketstat/spiders/items.py

# -*- coding: utf-8 -*-

import scrapy


class MarketstatItem(scrapy.Item):
    date = scrapy.Field()
    name = scrapy.Field()
    expected_value = scrapy.Field()
    preliminary_value = scrapy.Field()
    confirmed_value = scrapy.Field()


 

Spider を作成

次に、以下のコマンドを実行して、Spider のひな形を作成します。

$ scrapy genspider boj www3.boj.or.jp

 
作成された Spider のひな形を以下のように修正します。

marketstat/spiders/boj.py

# -*- coding: utf-8 -*-

from datetime import datetime
import scrapy
from pytz import timezone

from ..items import MarketstatItem


class BojSpider(scrapy.Spider):
    name = "boj"
    allowed_domains = ["www3.boj.or.jp"]
    date = datetime.now(timezone('Asia/Tokyo')).strftime('%y%m%d')
    start_urls = [
        'http://www3.boj.or.jp/market/jp/stat/jx{date}.htm'.format(date=date),
    ]

    def parse(self, response):
        for sel in response.css('table tr'):
            item = MarketstatItem()
            item['date'] = self.date
            item['name'] = sel.css('td::text').extract_first()
            item['expected_value'] = sel.css('td:nth-last-child(3)::text').extract_first()
            item['preliminary_value'] = sel.css('td:nth-last-child(2)::text').extract_first()
            item['confirmed_value'] = sel.css('td:nth-last-child(1)::text').extract_first()
            yield item

parse メソッドを修正して、スクレイピングしたデータを格納した Item オブジェクトを yeild するようにします。


ちなみに、scrapy shell コマンドを実行することで、ipython が立ち上がってスクレイピングのデバッグ実行ができるため、目的の Webページの CSS要素を特定するのに便利です。

$ scrapy shell http://www3.boj.or.jp/market/jp/stat/jx170301.htm
    ・
    ・
In [1]: print(response.css('table tr')[1].css('td::text')[0].extract())
銀行券要因

(参考)http://qiita.com/ttomoaki/items/05d3dc104a695f939d63



なお、

sel.css('td::text')[0].extract()

とせず、

sel.css('td::text').extract_first()

とすることで、指定した要素が見つからない場合に IndexError が発生せずに None が返されるので非常に使い勝手がよいです。また、「::text」を付けないと HTMLタグが含まれた状態で値が取れてしまうので、これも必須のテクでしょう。


(参考)Scrapy Tutorial — Scrapy 1.3.3 documentation



 

スクレイピング実行

crawl コマンドの引数に Spider名(今回の例では「boj」)を指定します。

なお、-o オプションで出力するファイル名を指定することができます。

$ scrapy crawl boj -o test.csv


test.csv

date,expected_value,preliminary_value,name,confirmed_value
170301,,,,
170301,-600,-600,銀行券要因,
170301,"-11,100","-13,300",財政等要因,
170301,"-11,700","-13,900",資金過不足,
170301,"9,000","9,000",国債買入,
    ・
    ・


ここで、settings.py に

###############
# OUTPUT FILE #
###############
FEED_FORMAT = 'csv'
FEED_URI = '/Users/akiyoko/tmp/test.csv'

と書いておけば、-o オプションをいちいち指定する必要はありません(どちらも指定した場合は、-o オプションの方が優先されるようです)。


またここで、作成した Spider のインスタンス変数名を「FEED_URI」のプレースホルダとして使うことも可能です。

FEED_URI = '%(date)s.csv'


 

S3 に格納する方法

S3 に格納するのも簡単です。
例えば「marketstat」というバケットに格納するなら、settings.py に

###############
# OUTPUT FILE #
###############
FEED_FORMAT = 'csv'
FEED_URI = 's3://marketstat/%(name)s/%(date)s.csv'

###########
# AWS KEY #
###########
AWS_ACCESS_KEY_ID = 'AKIXXX'
AWS_SECRET_ACCESS_KEY = 'XXXXX'

とすればよいです。簡単ですね。


Spider に任意の引数を渡す

ちょっとした小技ですが、-a オプションを指定することで、Spider に任意の引数を渡すことができます。

(参考)スパイダー — Scrapy 1.2.2 ドキュメント

$ scrapy crawl boj -a date=170303


Spider 側からは、__init__ メソッド内で引数を受け取ることができます。
また、__init__ 内でインスタンス変数を上書きすることで、parse メソッドが実行される前にインスタンス変数の値を書き換えておくことが可能です。


marketstat/spiders/boj.py

class BojSpider(scrapy.Spider):
    name = "boj"
    allowed_domains = ["www3.boj.or.jp"]
    date = datetime.now(timezone('Asia/Tokyo')).strftime('%y%m%d')
    start_urls = [
        'http://www3.boj.or.jp/market/jp/stat/jx{date}.htm'.format(date=date),
    ]

    def __init__(self, date=None, *args, **kwargs):
        super(BojSpider, self).__init__(*args, **kwargs)
        if date is not None:
            self.date = date
            self.start_urls = [
                'http://www3.boj.or.jp/market/jp/stat/jx{date}.htm'.format(date=self.date),
            ]

    def parse(self, response):
        for sel in response.css('table tr'):
            item = MarketstatItem()
            item['date'] = self.date
            item['name'] = sel.css('td::text').extract_first()
            item['expected_value'] = sel.css('td:nth-last-child(3)::text').extract_first()
            item['preliminary_value'] = sel.css('td:nth-last-child(2)::text').extract_first()
            item['confirmed_value'] = sel.css('td:nth-last-child(1)::text').extract_first()
            yield item


 

シェルを作成

日付を範囲指定してクローリングするなら、例えば以下のようなシェルを作成すればよいでしょう。

#!/bin/bash

START_DATE=170220
END_DATE=170301

for (( DATE=$START_DATE ; $DATE <= $END_DATE ; DATE=`date -j -v+1d -f %y%m%d $DATE +%y%m%d` )) ; do
   echo $DATE
   scrapy crawl boj -a date=$DATE
done


(参考)



なお、大量のリクエストが発生する場合は、settings.py に

DOWNLOAD_DELAY = 3  # or 30 ?

などと設定しておきましょう。


(参考)Settings — Scrapy 1.3.3 documentation


 

まとめ

今回、知識ゼロから Scrapy を使って Web スクレイピングを試してみました。
実際使ってみて、仕組み(どこを触ればいいか)さえ分かってしまえば、実装部分も少なくて非常に便利に使えることが実感できました。

次は、S3 に格納した CSVファイルを Amazon Athena と QuickSight を使ってデータ分析していきたいと考えています。

Vagrant と Ansible を連携させて Ubuntu 14.04 に MySQL, PostgreSQL を provision する手順

Ansible Vagrant MySQL PostgreSQL 開発環境 Ubuntu

AnsibleとVagrantで開発環境を構築する - さくらのナレッジ
という記事を読んで、開発環境の Ubuntu サーバに MySQL や PostgreSQL をインストールするなら、Vagrant と Ansible を連携させた方がやりやすいな、と思ったのでメモがてらまとめておきたいと思います。


ベースとしては、以前使った Ansible Galaxy を使います。
具体的には、

インストールします。


Vagrant 以外の仮想サーバや通常のサーバに対して、MySQL や PostgreSQL を簡単にインストールする手順については、以下の過去記事を参照してください。

<過去記事>
akiyoko.hatenablog.jp

akiyoko.hatenablog.jp



ホスト

  • macOS Sierra 10.12.3
  • Vagrant 1.9.1
  • VirtualBox 5.1.14


macOS Sierra に Vagrant および VirtualBox をインストールする手順については、以下を参照してください。

<過去記事>
akiyoko.hatenablog.jp


ゲスト

  • Ubuntu 14.04

ゲストマシンのプライベート IPアドレスは「192.168.33.10」に設定しておきます。


データベース

  • MySQL 5.5.54
  • PostgreSQL 9.3.16


インストールと同時に以下の設定もおこなう想定です。

項目 設定内容
データベース名 myproject
データベースユーザ myprojectuser
データベースユーザパスワード myprojectuserpass


ちなみに、MySQL の root のパスワードは「rootpass」となります。
また、PostgreSQL の場合は「postgres」という Linuxユーザが作成されます。



 

MySQL のインストール

MySQL は ANXS.mysql でインストールします。

$ cd ~/dev/vagrant/ubuntu14
$ mkdir provisioning
$ ansible-galaxy install ANXS.mysql -p provisioning/roles


etc_mysql_my.cnf.j2 ファイル内の「character_set_server」および「collation_server」のキーワードを修正します。 *1

$ sed -i '' 's/^character_set_server/character-set-server/g' provisioning/roles/ANXS.mysql/templates/etc_mysql_my.cnf.j2
$ sed -i '' 's/^collation_server/collation-server/g' provisioning/roles/ANXS.mysql/templates/etc_mysql_my.cnf.j2


provisioning/hosts

[db-servers]
192.168.33.10


provisioning/site.yml

- hosts: db-servers
  become: true
  user: vagrant
  vars_files:
    - vars/mysql.yml
  roles:
    - { role: ANXS.mysql }

 

$ mkdir provisioning/vars

provisioning/vars/mysql.yml

mysql_current_root_password: ''
mysql_root_password: rootpass
mysql_databases:
  - name: myproject
mysql_users:
  - name: myprojectuser
    pass: myprojectuserpass
    priv: "myproject.*:ALL"


最終的なディレクトリ構成はこのような感じになります。

~/dev/vagrant/ubuntu14/
├── Vagrantfile
└── provisioning
    ├── hosts
    ├── roles
    │   └── ANXS.mysql
    │       ・
    │       ・
    ├── site.retry
    ├── site.yml
    └── vars
        └── mysql.yml


Vagrantfile

    ・
    ・
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.10"
    ・
    ・
  # Enable provisioning with a shell script. Additional provisioners such as
  # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/site.yml"
    ansible.inventory_path = "provisioning/hosts"
    ansible.limit = "all"
  end


 

provision

サーバを初回起動する際に provision が実行されます。

$ vagrant up


起動済みのサーバには、以下のコマンドを実行することで provision が実行されます。

$ vagrant provision

  or

$ ansible-playbook -i provisioning/hosts provisioning/site.yml -k -vv

後者のコマンドの場合には、vagrant ユーザのパスワードが要求されます。

パスワードを入力したくない場合は、

$ vagrant ssh-config --host 192.168.33.10 >> ~/.ssh/config

### 念のためパーミッションを変更
$ sudo chmod 600 ~/.ssh/config

を設定しておけば、

$ ansible-playbook -i provisioning/hosts provisioning/site.yml -vv

で、パスワード無しで実行可能です。

 

動作確認

$ vagrant ssh

  or

$ ssh vagrant@192.168.33.10

でサーバにログインして、

$ mysql -u root -p

で動作確認します。




 

PostgreSQL のインストール

PostgreSQL は ANXS.postgresql でインストールします。

$ mkdir provisioning
$ ansible-galaxy install ANXS.postgresql -p provisioning/roles

provisioning/hosts

[db-servers]
192.168.33.110

provisioning/site.yml

- hosts: db-servers
  become: true
  user: vagrant
  vars_files:
    - vars/postgresql.yml
  roles:
    - { role: ANXS.postgresql }

 

$ mkdir provisioning/vars

provisioning/vars/postgresql.yml

postgresql_databases:
  - name: myproject
postgresql_users:
  - name: myprojectuser
    pass: myprojectuserpass
postgresql_user_privileges:
  - name: myprojectuser
    db: myproject
    priv: "ALL"


最終的なディレクトリ構成はこのような感じになります。

~/dev/vagrant/ubuntu14/
├── Vagrantfile
└── provisioning
    ├── hosts
    ├── roles
    │   └── ANXS.postgresql
    │       ・
    │       ・
    ├── site.retry
    ├── site.yml
    └── vars
        └── postgresql.yml


Vagrantfile

    ・
    ・
  # Create a private network, which allows host-only access to the machine
  # using a specific IP.
  config.vm.network "private_network", ip: "192.168.33.10"
    ・
    ・
  # Enable provisioning with a shell script. Additional provisioners such as
  # Puppet, Chef, Ansible, Salt, and Docker are also available. Please see the
  # documentation for more information about their specific syntax and use.
  # config.vm.provision "shell", inline: <<-SHELL
  #   apt-get update
  #   apt-get install -y apache2
  # SHELL
  config.vm.provision "ansible" do |ansible|
    ansible.playbook = "provisioning/site.yml"
    ansible.inventory_path = "provisioning/hosts"
    ansible.limit = "all"
  end


 

provision

サーバを初回起動する際に provision が実行されます。

$ vagrant up


起動済みのサーバには、以下のコマンドを実行することで provision が実行されます。

$ vagrant provision

  or

$ ansible-playbook -i provisioning/hosts provisioning/site.yml -k -vv

後者のコマンドの場合には、vagrant ユーザのパスワードが要求されます。

パスワードを入力したくない場合は、

$ vagrant ssh-config --host 192.168.33.10 >> ~/.ssh/config

### 念のためパーミッションを変更
$ sudo chmod 600 ~/.ssh/config

を設定しておけば、

$ ansible-playbook -i provisioning/hosts provisioning/site.yml -vv

で、パスワード無しで実行可能です。

 

動作確認

$ vagrant ssh

  or

$ ssh vagrant@192.168.33.10

でサーバにログインして、

$ psql -U postgres
  or
$ sudo su postgres
$ psql

で動作確認します。

おまけ

### ユーザ一覧
postgres=# \du

### データベース一覧
postgres=# \l

### データベース接続
postgres=# \c myproject

### テーブル一覧
myproject=# \d
myproject=# \dt

### 終了
myproject=# \q


 

書籍

PyCharm のオレオレ最強設定

PyCharm 開発環境 Python

先日、「最強のPython開発環境 PyCharmのすゝめ - Qiita」という記事がホットエントリーに上がっていましたが、かくいう私も、PyCharm は Python の統合開発環境(IDE)としてまさに最強だと考えています。


www.jetbrains.com



PyCharm(を含めた JetBrains 製品)は「out of the box(アウト・オブ・ボックス:箱から取り出してすぐに使える、難しい設定などは一切なしで使える)」というのが大きな魅力のひとつですが、今回紹介する環境設定をすることで更なる実力を発揮させることができます。


今回紹介するのはあくまで私の(オレオレ)最強設定ですので、異論・反論は緩やかな範囲でお願いします。。


 

事前準備(インストール)

まずはインストールについて。

環境

  • Mac OS:10.12.3(Sierra)
  • PyCharm:2016.3.2

インストール方法

少し前までは Homebrew Cask でインストールしていたのですが、Homebrew Cask が管理している PyCharm のバージョン情報がなかなか最新化されなかったりするので、公式サイトからアプリをダウンロードしてインストールするスタイルに変えました。


ということで、https://www.jetbrains.com/pycharm/download/ から、それぞれの環境に合わせたものをダウンロードします。

f:id:akiyoko:20170309233705p:plain



私は有償の「Professional Edition」を使っていますが、無償の「Community Edition」でも大抵の機能は使えますのでご安心を。

(参考)PyCharm :: Editions Comparison


なお、Professional Edition のライセンス料金はサブスクリプション方式になっていて、例えばパーソナルライセンスだと、

1年目 US $ 89.00 /年
2年目 US $ 71.00 /年
3年目以降 US $ 53.00 /年

となっています。

(参考)PyCharm: JetBrains Toolbox subscription





 

環境設定

上部メニューの[PyCharm] > [Preferences](ショートカットは「⌘ + ,」)から、PyCharm の環境設定が変更できます。

1.テーマ設定

[Appearance & Behavior] > [Appearance]

[UI Options]のTheme を「Darcura」(少し暗めのテーマ)に変更します。

f:id:akiyoko:20170310003027p:plain

理由:かっこいいから。

2.メモリ設定

[Appearance & Behavior] > [Appearance]

[Window Options]の「Show memory indicator」にチェックを入れます。

f:id:akiyoko:20170310003158p:plain

理由:メモリをクリアできるように。右下に使用メモリ量のインジケーターが表示されますが、これをクリックすることでメモリをクリアすることができるようになります。


f:id:akiyoko:20170310003752p:plain:w300


またここで、デフォルトのヒープメモリサイズを 2GB くらいに増やしておきます。

[Help] > [Edit Custom VM Options]

を選択すると、ファイルがまだ存在していなければ、
~/Library/Preferences/PyCharm2016.3/pycharm.vmoptions
が作成されます。

# custom PyCharm VM options

-Xms128m
-Xmx750m
-XX:ReservedCodeCacheSize=240m
-XX:+UseCompressedOops

これを、

# custom PyCharm VM options

-Xms128m
-Xmx2000m
-XX:ReservedCodeCacheSize=240m
-XX:+UseCompressedOops

などと書き換えて、PyCharm を再起動します。

(参考)IntelliJ IDEAのヒープサイズを増やす - Qiita



 

3.エディタ表示

[Editor] > [General] > [Appearance]

[Show line numbers]および[Show whitespaces]にチェックを入れます。

f:id:akiyoko:20170310003817p:plain

理由:
 ・行番号を表示したいから。
 ・空白スペースを可視化したいから。


 

4.コード補完

[Editor] > [General] > [Code Completion]

[Case sensitive completion]に「None」を選択。

f:id:akiyoko:20170310003834p:plain

理由:コード補完(control + space)の際、大文字小文字を区別しないで補完してほしいから。


 

5.タブの表示数

[Editor] > [General] > [Editor Tabs]

[Tab Closing Policy]の Tab limit を「10」から「50」に変更。

f:id:akiyoko:20170310003948p:plain

理由:タブを 10 個以上開くと勝手に閉じちゃう設定だと使いにくいから。


 

6.フォントサイズ設定

6.1. エディタのフォントサイズ

[Preferences] > [Editor] > [Color & Fonts] > [Font]

Scheme から[Save As]で、「Darcula copy」などという名前でコピーすると、フォントサイズが変更できるようになります。

「Size:10」くらいにしておきます。

f:id:akiyoko:20170310004021p:plain
f:id:akiyoko:20170310004036p:plain

理由:MacBook のディスプレイが 13インチと小さいので、できるだけ広い範囲でコードを見たいから。

6.2. コンソールのフォントサイズ

[Preferences] > [Editor] > [Color & Fonts] > [Console Font]

エディタとコンソールのフォントサイズは別々に設定が必要です。

f:id:akiyoko:20170310005558p:plain

こちらも「Size:10」くらいにしておきます。



 

7.PEP8 違反の警告

[Editor] > [Inspections]

  • [PEP8 coding style violation]
  • [PEP8 naming conversion violation]

を「week warning」から「warning」に変更。

f:id:akiyoko:20170310004146p:plain

理由:PEP8 違反の警告をワーニングに上げたいから。


(参考)最強のPython統合開発環境PyCharm - Qiita


 

8.プラグイン

[Plugins] で、以下のプラグインをインストールします。

  • CodeGlance(Sublime Text のミニマップ風)
  • gfm(GitHub Markdown プラグイン)
  • .ignore

インストールしていないプラグインは、検索して「Install」ボタンをクリックするとオンラインのリポジトリからダウンロードしてインストールすることができます。超便利。

f:id:akiyoko:20170310004817p:plain
f:id:akiyoko:20170310004832p:plain


 

9.Project ビューの表示設定

Project ビューの歯車アイコンをクリックして、

  • [Autoscroll to Source](Projectビューからシングルクリックでソースビューを開く)
  • [Autoscroll from Source](ソースビューを開くとProjectビューに該当モジュールがフォーカスする)

にチェックを入れておきます。

f:id:akiyoko:20170310010217p:plain



 

便利なショートカットなど

最後に非常に便利なショートカットをいくつか紹介します。

JetBrains 公式のチートシート もありますが、さすがに全部覚えきれませんよね。。

 

検索
ショートカット 説明
shift + ⌘ + f grep検索
opt + ⌘ + ↓ (↑) grep検索結果の前後を表示
⌘ + f ファイル内検索
(shift +) ⌘ + g ファイル内検索結果の前後を表示
⌘ + b 関数・メソッドの宣言にジャンプ
opt + ⌘ + F7 関数・メソッドを使用している箇所を検索
opt + ⌘ + ← (→) 履歴の前後を表示

 

タブ移動
ショートカット 説明
control + ← (→) タブ移動

 

ファイルを開く
ショートカット 説明
shift x 2 (素早く2回) クイック検索
⌘ + e 最近開いたファイルを開く
shift + ⌘ + o ファイル名でファイルを開く

 

差分表示
ショートカット 説明
(Project ビューで) ⌘ + d 別ファイルとの Diff

 

その他
ショートカット 説明
⌘ + ↑ ナビゲーションバーを操作
opt + F12 Terminal を開閉
shift + ⌘ + a 利用できるアクションを検索


 

まとめ

デフォルトの環境設定を何も弄らなくても、PyCharm は快適に動いてくれます。
しかしながら、今回のような環境設定をすると、PyCharm はその秘めたる力を開放してくれます。まだ見つけられていない素敵な設定を見つけたら、この記事をどんどん更新していきます。

それでは、素敵な PyCharm ライフを!

「ビットコインとか勉強会#5」に参加してきました

勉強会 仮想通貨

会場

株式会社オウケイウェイヴ 東京本社
東京都渋谷区恵比寿1-19-15(ウノサワ東急ビル5階)

Twitter

twitter.com


 

全体の感想など

前回に続いて二度目の「ビットコインとか勉強会」でしたが、今回はビットコイン自体の話ではなく、それに付随する周辺事情の話題がメインでした。


<過去記事>
akiyoko.hatenablog.jp


トークン? CounterParty? OpenAssets? the DAO?
恥ずかしながら、話を聞いてもあまり理解が出来なかったので、勉強会の後で少し調べてみました。ついでにビットコインの仕組みについても少し詳しく読んでみました。


ビットコインの仕組み

トークンについて


要するに「トークン」とは、「ブロックチェーン上で発行された独自コイン」のことなのですね。まだまだ勉強が足りないようです。。


ブロックチェーンは革命なのか? – アゴラ(中村 伊知哉)」を読んで、現在積ん読している本。もうすぐ読み始める予定です。







 

ビットコイン上に発行できるトークンって何?

小川 晃平 氏(AccumBit, inc CEO)



CounterParty、OpenAssets、Coluを比較しつつ、カラードコインの面白さについて解説。

  • カラードコイン
    • トークンのやりとりができるプロトコル
    • Ethereumと違ってとスマートコントラクトは含まれない
    • CounterParty, Colu, OpenAssets Protocol, etc
    • OP_RETURN(Bitcoinの仕様上、上限80byteまで)
      • 宛先が要らない空のアウトプット
  • 何が実現できる?
    • 例えば、分散化不動産取引とかが実現する?
    • 日本円を Bitcoin 上で取り引き
      • でも、1byteあたり200satoshiのトランザクションの取り引き手数料が掛かる?
    • ゲーム上のトークンが他のゲームでも使えたり、後で売れたりとか
      • マネーロンダリングに使われちゃう?規制化??
    • 宝石のトレースシステム、メタ情報を追加
    • 「ある物」を買える権利をトークン化??
  • 実用化に向けた問題点
    • マネーロンダリング
    • 法律の問題(5月・6月に施行される法律でトークンが壊滅しちゃうかも??)
    • トークン上がる上がる詐欺
    • ウォレットのバグ



 

SPVウォレットを作ってみた。

澤田 健都 氏(株式会社クロスブリッジ)


docs.google.com

  • Bitcoinを使ったサービスを作りたい!
  • ウォレットはいろいろある
    • SaaS だと、Block.io, Blockchain.info, BitGo
  • 自分でノードを立てよう!
    • bitcoin.d, C++
    • Bitcore, Node.js
      • bitpay??
    • btcd, Go
  • ↑は Full-node で使いづらい。。じゃあ、SPVノードを作ろう!!
    • 事前に必要なデータの条件(フィルタ)を伝えることができるので、Full-node に比べて無駄がない
    • ブルームフィルタは偽陽性(False Positive)
  • SPV のデメリット
    • プライバシー問題
      • フィルタを敢えて曖昧にしておく?
    • TXの署名の検証ができない
      • 信頼できるpeerを選ぶ? 0-confirmationを受け付けない、とかで解決?
  • 主なSPVの実装
    • Bitcoinj, Java
      • Androidアプリで多数利用しているっぽい
    • BreadWallet, Objective-C

「簡単、クレカ決済! PAY.JPを使ったクレカ決済の仕組み・開発運用時の考慮点について」に参加してきました

勉強会 決済

会場

株式会社ビズリーチ
東京都渋谷区渋谷2-15-1 渋谷クロスタワー 12F


 

全体の感想など

最近、決済関連の勉強会が頻繁に開催されているような気がするのですが、今回は、WebPay サービス終了にあたって公式移行サービスを発表したことで最近話題になった「PAY.JP」の勉強会です。

勉強会の会場はビズリーチ。オフィスにビーチやらグリーンがあるというのを耳にしたことがあったので、まずはそっちに興味津々。

行ってみると、ありましたー!!

f:id:akiyoko:20170214191851j:plain:w500
(グリーンの逆側しか撮ってなかったのですが雰囲気は伝わるかと。。)


気になる方は、こちらの記事をどうぞ。
hrnabi.com



それはさておき、今回の勉強会では実際に「PAY.JP」を使ってサービスを開発・運営した開発者の意見が聞けたのはすごくよかったです。選定の経緯としては、昨年中に PAY.JP のほか「Yahoo!ウォレット FastPay」「WebPay」「Cybersource」(仕組みが違いすぎて却下)を比較検討して、開発しやすそうということで採用に至ったとのこと。その時点ではまだ「Stripe」は本番利用できていなかったとは思うのですが、「PayPal」や「LINE Pay」なども検討に入れたのかどうかなども聞いてみたかったところです。


しかしながら結局、PAY.JP は越境EC には対応していないらしいので(要確認)、私のニーズに合うのは Stripe か PayPal のどちらかかなぁと思いました。


 

簡単、クレカ決済! PAY.JPを使ったクレカ決済の仕組み・開発運用時の考慮点について

小山健太



  • 求められるもの
    • 工数掛けたくない
    • セキュリティは担保したい
    • 堅牢性
    • 保守性
  • コード自体をシンプルにしよう
  • PAY.JP の仕組み
    • カード情報をトークン化
  • できること
    • クレカ情報の保存(暗号化した状態)
    • 支払い、与信枠確保、返金
    • 定期課金(月・年単位、トライアル期間)
    • 支払い時や定期課金時にWebhook送信
  • ドキュメントが日本語
  • カード情報を持つ企業は以下のいずれかが必要
    • グローバルセキュリティ基準の「PCI DSS」を取得
    • 書くカードブランド制定のセキュリティ基準プログラムに準拠
  • サービス選定基準
    • 料金
    • 対応カードブランド
    • 対応通過
    • 不正検知オプションサービス
    • 入金サイクル
    • サービスの継続性
    • 開発効率・運用性
  • 運用時は、エラーログやレスポンスを保存しておくべし!
  • 開発時の難しかったポイント
    • 問題①:API越しのデータとの不整合
      • そもそも重複データを持たせないようにする
      • データ不整合が発生した場合はエラーを出して検知し、運用でカバー!?
      • データ不整合が発生した場合は、API経由でPAY.JP側もロールバックしちゃう?!
    • 問題②:外部サービスへのリクエストがタイムアウトしたら?
    • リクエストタイムアウトの設定時間を長めに
    • エラーログを出して検出
    • 問題③:HTTPリクエストの結果を待って次のリクエストを・・と処理が同期的になりがち
  • その他
    • 電子マネーはサポートしてないが、Apple Pay、PAY.JP アカウントのみ対応
    • ログは fluentd で ElasticSearch に保存して、エラーログだけ Slack に通知
    • テスト環境と本番環境の二環境しかない、Admin画面がしょぼいのはデメリット