2015年8月23日日曜日

ファビコン(favicon.ico)と、スマホのホーム画面用アイコンの作成

先日、Google App Engineのログを眺めていたら、Webブラウザからibbwatch.appspot.comにアクセスがあるたびに、"favicon.ico"を読もうとして失敗しているようでした。
もともと実験的に立ち上げたサービスだし、ファビコンでデコる必要もないかと思い、favicon.icoは設置していませんでした。
ただ、どうやら大抵のWebブラウザは、一度のアクセスでfavicon.icoを読めなかったら、もう一度トライする仕様になっているようです。
ログの中で、1回アクセスがあるたびにfavicon.icoの読み込みを2回ずつトライして2回とも404エラーになっているのです。
気にしなければいいのしょうけど、なんか気持ち悪いですよね。
そこで、ファビコンを設置すべく、いろいろ調べましたので備忘録も兼ねて少しまとめておきます。

[ファビコン]

  • 基本は".ico"形式で作成し、"favicon.ico"というファイル名でルートに置く
    はじめにIE5の機能拡張としてマイクロソフトが独自に設定したため、Windows用のアイコンフォーマットとして既に使われていた".ico"形式が採用された。
  • 別の画像ファイル形式を使うことも可能。ファイル名等も変更可能
    現在はIE以外にも多くのWebブラウザで採用されており、GIFやPNGなど、".ico"でない画像ファイル形式も使える。HTML内部に、<link>タグを使って、ファイル名、ファイルの格納場所などを指定できる。
もともとは、「お気に入り」にブックマークしたとき、たくさんあるブックマークの中から、目的のサイトを見つけやすくするための、IE5の独自機能だったのですね。
どうやら、マイクロソフトが独自に考えたものなので、HTMLを勝手に拡張するわけにいかず、格納場所とファイル名が固定されていたという経緯があった模様。

IE5というと、1999年に公開されているので、もはや前世紀の話ですが、iPhoneの登場により「アイコンでブックマークを目立たせる」という機能に新風が吹きます。

iPhoneの大ブームにより、一気にスマホが普及しますが、iPhoneはWebのブックマークをホーム画面に貼り付けることができます。このとき使われる「ウェブクリップアイコン」は、サーバーのルートに置かれた"apple-touch-icon.png"という名前のPNG形式の画像ファイルから取得しているんです。

一気に普及すると同じ事がやりたくなるんでしょうか? 数を持っていると強気になるのかもしれません。20世紀のマイクロソフトと同じことを21世紀のアップルもやっているんですね。
「売れている者の勝ち」というと、資本主義的で差別的な感じですが、「沢山のお客様に支持されている者の勝ち」というと民主主義的です。
そういう気持ちはわからなくもないですね。

こちらも今は、HTMLの<link>タグから名前や置き場所を変えられるようになっているようで、Andoroidはこのタグを見に行っているようです。

[ウェブクリップアイコン]
  • 基本は、PNG形式で作成し"apple-touch-icon.png"というファイル名でルートに置く
    最初にアップルがiPhone用にそう決めた。
  • ファイル名等変更可能
    現在はHTMLの中に<link>タグを使ってパスを指定可能。
● 作業

ということで、まずはアイコンを作ります。

16x16、32x32、64x64、180x180のアイコンをPNG形式で作りました。
これを先ほどのサイトでまとめて、"favicon.ico"というファイルに変換します。
そして、180x180は"apple-touch-icon.png"というファイル名にします。
これら2つのファイルをルートに置きます。
Webブラウザから見えるように、"app.yaml"の"handlers:"のところに、下記のように追記します。

- url: /favicon\.ico
  static_files: favicon.ico
  upload: favicon.ico
 
- url: /apple-touch-icon\.png
  static_files: apple-touch-icon.png
  upload: apple-touch-icon.png
そして、HTMLに<link>タグを追記します。
<link rel="apple-touch-icon" href="/apple-touch-icon.png" />
とりあえずこれでPC用のブラウザとiPhoneとAndroidのホーム画面にアイコンが表示できるようになりました。


[参考]

2015年8月17日月曜日

Twitter つぶやき機能追加

Bitcoin価格評価システムにTwitterへの投稿機能を付けました。価格が高いor安いと判断したら、その旨つぶやきます。
アカウントは @BTCcheck です。ぜひフォローしてみてください。

Google App Engine から、Twitterに投稿するのはちょっと面倒でした。
Pythonからツイートするといえば、requests-oauthlib が比較的有名で、python-twitter でも内部でrequests-oauthlibが呼ばれているようです。
requests-oauthlibの情報は検索すればたくさん出てくるのですが、Google App Engineからは使えませんでした。
でも、蛇の道はヘビといいますか、さすがインターネット、必ず先人がおられます。先人たちの残してくださった情報をもとに、どうにかツイート機能を実装することができました。
一番の決め手は AppEngine-OAuth-Library です。この中の"oauth.py"を使います。
使い方は、ここTwitterボットをOAuthに対応させてみた - Google App Engine(Python)」を参考にさせていただきました。

いろいろ調べて遠回りしてしまったので、簡単に作業内容をまとめておきます。
大きな流れとしては、以下の通りです。

  1. AppEngine-OAuth-Library の中の"oauth.py"をコピーします。
    ツイートするスクリプトが"tweet.py"だととすれば、"tweet.py"と同じ場所に置くのがわかりやすくていいでしょう。
  2. "oauth.py"の53行目あたり、"import json"をコメントアウトして、すぐ上の行にコメントアウトされている"#from django.utils import simplejson as json"の頭の"#"を外します。
    もし、うまく動作しない場合は、djangoのライブラリ設定がうまくできていないと思われますが、いろいろ考えるのが面倒なら、ここ(https://pypi.python.org/pypi/simplejson)からsimplejsonをダウンロードして、"simplejson"というフォルダを"oauth.py"と同じディレクトリに置き、53行目を"import simplejson as json"と書き換えるという手もあります。
  3. TwitterボットをOAuthに対応させてみた - Google App Engine(Python)」に書かれているサンプルを参考に、ほぼほぼこのまま使わせていただきます。
    ただし、Twitterに投稿のリクエストをするURL"http://twitter.com/statuses/update.json"は、少し古いようで、"https://api.twitter.com/1.1/statuses/update.json"に書き換える必要があります。
    変数paramを書き換えてからTweetHandlerをwebapp.WSGIApplicationに渡してやれば、ツイート内容を変えることができます。
    "TweetHandler.get.param = {'status' : u'新しくつぶやく内容'}"とすれば、ツイート内容を変更できるはずです。
    現在運用中のBitcoin価格評価システムでは、いろいろいじくっていたので、paramはTweetHandlerの直下にあります。したがって、"TweetHandler.param = {'status' : u'新しくつぶやく内容'}"を実行してから、"application = webapp.WSGIApplication([('tweet.pyを呼ぶURL', TweetHandler)], debug=DEBUG)"を実行しています。

先人たちの残してくれたライブラリや各種情報のおかげで、なんとかツイート機能を追加できました。ありがとうございます!

ちなみにOAuth認証の「OAuth」ですが、「オー オース」と発音するそうです。(参照:Wikipedia)

2015年8月14日金曜日

Google App Engine の Cloud Datastore を とにかく簡単に使う

今回、Bitcoin価格評価システムを立ち上げるにあたり、定期的にcoincheck取引所の取引状況を取得するために、Google App Engine を使いました。
もともと、ローカルPC上にPythonで組み上げたシステムがあったので、これを年中動かしっぱなしにできるよう、Google App Engine に移植しました。
Google App Engine は、Java、PHP、Go言語などでも開発できるようですが、Pythonが使い慣れているので、とりあえずPython(バージョン2.7)を使うことにします。

ローカルPC上に作っていたシステムは、Pythonの標準ライブラリに含まれているSQLite3を使っていました。
SQLiteは使い慣れると大変便利で、まるで配列に保存するかのように使えます。取得したデータをとりあえずSQLiteデータベースに放り込んで、重複行を削除したり時間順に並び替えたりという作業のほとんどはSQLiteのコマンドを叩いていました。
App Engine上では、Pythonの標準ライブラリに含まれているSQLite3が使えないので、別の方法を考えなくてはいけません。
App Engineからは、Cloud SQLが使えます。しかし、これには無料枠がありません。それに対して、Cloud Datastoreは、App Engineサービス開始当初から標準でサポートされているデータベースで、無料枠があります。(結局、無料枠は一瞬で使い果たしますが……それについては別の機会に)
本格的なSQLが使いたいわけではなく、ちょっと配列代わりに使いたいだけなので、Cloud Datastoreを使うことにします。

参考までに、今日時点のCloud Datastoreの1日あたりの無料割り当て枠は以下の通りです。
  • 5 万回(読み取り/書き込み/小規模な操作)
  • 1 GB ストレージ
この無料枠につられて、まんまとCloud Datastoreを使う羽目になってしまったのです……

さて、Cloud Datastoreですが、SQLなどのリレーショナルデータベースとはちょっとイメージが違います。同じ「種別」の「エンティティ」の塊をひとつのデータベースとして扱うという感じです。リレーショナルデータベースのイメージからすると、ひとつのデータベースというよりは、テーブルのイメージです。
そして、エンティティ一つ一つが行にあたり、エンティティの「プロパティ」が列(フィールド)にあたります。
Pythonの中では、種別がクラス、エンティティがそのクラスから生成されたオブジェクト、プロパティがそのオブジェクトのメンバー変数で表現されています。
ちょっとややこしくなったので表にまとめます。

リレーショナルデータべーステーブルフィールド(列)
Cloud Datastore種別エンティティプロパティ
Python API での表現クラスオブジェクトメンバー変数
とりあえずこんなイメージで、ざっくり理解しておきます。

とにかくできるだけ簡単にCloud Datastoreを使い始めたいというのであれば、迷わずExpandoクラスを使えばいいでしょう。
# -*- coding: utf-8 -*-
import google.appengine.ext.db as gdb
class Mydb(gdb.Expando):    # Expandoクラスを継承したクラスを作成
    pass
BTCdb = Mydb()    # オブジェクトを生成
BTCdb.data = 34000     # メンバー変数に値を代入
BTCdb.put()     # put()でデータストアに保存
これだけで、テーブルを作って、フィールド(data=34000)を一つ持つ行を保存できました。
Pythonでは、クラス定義の中でオブジェクトのメンバー変数を定義する必要がなく、オブジェクトを生成した後からメンバー変数を作ってやれば、いくらでも増やすことができます。
ですので、Cloud Datastoreのプロパティ(リレーショナルデータベースのフィールド)をメンバー変数を増やすことで、後からいくらでも増やすことができるのです。

データを蓄えるだけなら、一度、put()を実行してしまえば、メンバー変数の中身はデータストアに保存されているので、オブジェクト自体を保持しておく必要はありません。
BTCdb = Mydb()
BTCdb.data = 34000
BTCdb.put()
の部分をどんどん繰り返してやれば、オブジェクトBTCdbが上書きされていくのでどんどんCloud Datastoreにデータが蓄積されていきます。

データの取り出しも簡単で、
q = Mydb.all()
と、するでけです。
for i in q:
    print i.data 
と、実行してやれば、先ほど保存したデータを表示することができます。

また、取り出すだけならGQLというSQLによく似たコマンドがあり、これを叩くことで、リレーショナルデータベースと同じように扱うことができます。

こんな感じで、Cloud Datastoreは配列に保存する感覚でデータを永続的に保存でき、GQLを使ってリレーショナルデータベースのように扱うこともできます。
当初考えていたよりもずっと簡単に使うことができした。

2015年8月13日木曜日

ひとまず、Bitcoinの価格を評価するシステムを作ってみました。

Bitcoinの自動売買システムを作ろうと思っています。
Bitcoinに限らず、株でもFXでも、基本は安いときに買って高いときに売る。
それはわかっているのですが、いま、目の前に表示されている価格が高いのか安いのか、それがわかりません。
まずは、買うか買わないかを決断する決め手として、高いか安いかを判定するシステムを作ってみました。
こちらです。


市場はcoincheckを見ています。
ボリンジャーバンドの考え方を参考に、統計的に高いか安いかを判定しています。

ただ、手数料0円の市場を対象に、細かく何度も売買を繰り返すことを前提にしていますので、一度の統計で見る範囲は最長で60分、取り引きが多いと自動的に範囲を狭めて、より短時間の統計を取るようにしています。
ですので、人手で売買する場合はもうすこし大きな利ザヤを狙う必要があるかもしれません。