FitbitのAPIを使う(2)APIをpythonで叩く準備

crulで叩いて情報を取得してもいいのですが、今回結果をDBに保存したいということもあり、pythonを使うことにしました。
今回はPythonで情報を取得するための準備です。

python-fitbitの準備

git clone https://github.com/orcasgit/python-fitbit

f:id:harucharuru:20200115171814p:plain

cd python-fitbit
sudo  pip3 install -r requirements/dev.txt

cherrypyを入れる

pip install cherrypy

f:id:harucharuru:20200115171951p:plain

requests requests-oauthlibを入れる

pip install requests requests-oauthlib

f:id:harucharuru:20200115172102p:plain


終わり!
Jupiterで行ったので、一応gistに載せて共有します。

FitbitのAPIを使う(1)API登録

FitbitのデータをDBに保存する方法について書いておきます。今回はAPI登録について

Fitbit の APIを管理するサイトにアクセス(必要に応じてログイン)
www.fitbit.com
f:id:harucharuru:20200115162851p:plain

右上のアプリを登録より、以下のように入力して登録
Application Name *:好きなアプリケーション名
Description *:アプリケーションについて
Application Website *:自分のサイト?
Organization *:personalとか?
Organization Website *:自分のサイト
Terms Of Service Url *:自分のサイト
Privacy Policy Url *:自分のサイト
OAuth 2.0 Application Type *:Personal
Callback URL *:http://127.0.0.1:8080/
Default Access Type *: Read & Write

登録するとclientIDなどが出てくる。ここにある情報は必要になるので、覚えておく。
f:id:harucharuru:20200115161706p:plain

OAuth 2.0 tutorial pageをクリックする

  • We've generated the authorization URL for you, all you need to do is just click on link below:

の下のリンクをクリックする
f:id:harucharuru:20200115161855p:plain

取得許可するデータを選択
f:id:harucharuru:20200115162027p:plain

次のようになればOK。このとき、出てきたurlをコピーしておく。
f:id:harucharuru:20200115162206p:plain

ひとつ前のサイトにコピーした張り付ける
f:id:harucharuru:20200115162446p:plain

この時表示されたtokenをコピーしておく(これがないとデータ取れない)

自作のマークシートを読み取りたいときに使うソフトウエアFormScanner

自作のマークシートを読み取り、csv化したいときに使うFormScannerについて書いておきます。
自作のマークシートを使いたいひと、無料のソフトウエアが良い人向けです。

FormScannerについて

私がこのソフトウエアを使うときに参考にさせてもらったサイト「FormScanner」の使い方に書いてありますように、

FormScanner概要
FormScannerはフリーのOMR(光学式マーク読取)ソフトウェアです。
オリジナルのマークシートによって、アンケートの集計やマークシートを用いた試験の採点ができます。
フリーソフトですので、もちろん無料で利用可能です。
また、ソフトウェアが現在進行形で開発され続けている点も強みであります。
ただし、日本語版は無く、また公式サイトのマニュアルも非常にざっくりしているため、本サイトを通じて日本に向けてFormScannerを紹介したいと思います。

本当に日本語版がなく、使いこなせるようになるまで時間がかかりました。以下、簡単な使い方を記しておきます。

FormScannerのダウンロード

FormScannerは、以下のリンクよりダウンロードしてexeファイルを実行すればOKです。
この時、javaがパソコンに入っている必要がありますので注意してください
FormScanner - Browse /1.1.3 at SourceForge.net

実行すると言語を聞かれます。Englishにしましょう
f:id:harucharuru:20200114172840p:plain

Next
f:id:harucharuru:20200114172903p:plain

同意してNext
f:id:harucharuru:20200114172925p:plain

アイコンをデスクトップに置くかどうか、は好きにしてください
f:id:harucharuru:20200114172959p:plain

これで完了です。Finishを押すと再起動がかかります。
f:id:harucharuru:20200114173027p:plain


もしも、アプリケーションを実行したときにJavaがないというエラーが出てきたら、
手順に従って無料JavaソフトウェアをダウンロードからJavaをダウンロードして、Pathを通してください。

FormScannerの使い方

FormScannerでは大きく分けて2つの作業があります
①読み取りテンプレートを作成する
②読み取りを行いcsv化する
でもその前に、
マークシートを作成する、スキャンする
が必要です。1つ1つ手順を追って説明します。

マークシートを作成する、スキャンする

読み取るためのマークシートを作成します。サンプルとして、下記のリンクにあるものを編集して使いました。
Forms - FormScanner
基本的には四隅に大きなマーク(サンプルだと円)が必要になります。
これがないと、読み取る際の目標点が見つからずマークシートを読み取ることができません。
私の場合は、以下のようなマークシートを作成しました。
f:id:harucharuru:20200114174150p:plain

そしてスキャンを行います。この時注意が必要なのですが、、、
必ず白黒スキャンしてください!グレースケール・カラースキャンをするときちんと読み取れないことがあります。
また、必ず画像ファイルにしてください(PDFなどの場合は、変換するなどの対応をしてください)

①読み取りテンプレートを作成する

読み取り用のテンプレートを作成していきます。
テンプレートを作成するときは、templateー>create…を選択します
f:id:harucharuru:20200114174630p:plain

読み取りを行う画像を選択します。
f:id:harucharuru:20200114174828p:plain

読み取るフィールド要素を聞いてきます。+で追加します。
f:id:harucharuru:20200114174948p:plain

今回は横方向に要素が並んでいるので~columnを選択します。
(縦方向の場合は~row)
f:id:harucharuru:20200114175014p:plain

要素名は何でもいいです。今回は何となくnumber。
マークシートの数は7つ、選択肢は10個あるので数を入力しておきます。
また複数選択を許容しないので、Igonre multiple choiceにチェックを付けます
(バグなのか、↑を一番最後に押さないと、confirmが押せません)
f:id:harucharuru:20200114175137p:plain

すると、マーカーに合わせて緑色の枠が出ていると思います。
きちんと自分のマーカーにあって出ていればOKです
f:id:harucharuru:20200114175456p:plain

そしてはじめと最後の要素をクリックします。今回でいうと、左上のマーク位置と、右下のマーク位置です。
左上のマーク位置↓
f:id:harucharuru:20200114175626p:plain

もしも、赤いマーカーが大きすぎるor小さすぎる場合にはoptionのマーカーサイズより変更できます。
f:id:harucharuru:20200114180308p:plain
f:id:harucharuru:20200114180327p:plain

両方クリックすると、座標が表示されます。問題なければ続けます。
そうでなければキャンセルすればもう一度クリックしなおすことができます。
今回、それぞれのマークは0~9の数字なので現在A,B,C…となっている部分を変更していきます。
f:id:harucharuru:20200114180005p:plain
f:id:harucharuru:20200114180128p:plain

これで問題なければテンプレートを保存します
f:id:harucharuru:20200114180228p:plain

②読み取りを行いcsv化する

まず、作成したテンプレートを読み込みます。
f:id:harucharuru:20200114181539p:plain

次のように出ていればOKです
f:id:harucharuru:20200114181617p:plain

読み込むマークシートを選択します
f:id:harucharuru:20200114181646p:plain
f:id:harucharuru:20200114181727p:plain

上にある再生ボタンを押せばcsvができます。あとは名前を付けて保存すればOKです。

日の出入りと気象データのスクレイピング

研究で気象データと日の出入りデータを使いたかったので、スクレイピングしてみました。

気象データ

気象庁|過去の気象データ検索
今までスクレイピングしたことがなかったので、以下のサイトをとても参考にしてプログラムを作成しました。
【最新】GoogleColaboratoryでもできる!気象庁の過去気象データをスクレイピングしてみた。 - Qiita
上のサイトでは複数の地点を一度にスクレイピングしていますが、私は一つの拠点でのスクレイピングをしました。
私のプログラムはここから→WeatherScraping · GitHub

日の出入りデータ

各地のこよみ (日の出入り、月の出入り、南中時、月齢) - 国立天文台暦計算室
上での経験を応用して、静岡県の日の出入りデータをスクレイピングするプログラムを作成しました。
また、ついでにDBへのuploadもしています。
プログラムはここから→WeatherScraping · GitHub

cakephp find でsql のcount使う方法と注意点

ひとつ前に書いたブログの内容、
sqlのcount使う方法と注意点 - My Note
は、実はCakePHPのfindで実装したかったときにはまった罠でした。
今回は、cakephpのfindでsqlのcount使う方法と注意点を書いていきます。

[ポイント]
cakephpのfindでsqlのcount使う方法と注意点
 →virtual fieldsを追加する必要がある

CakePHPsql のcount使う場合、次のようなプログラムを書きます。

SELECT `device_id`,count(if(`gender_id`=0,1,null)) as count0,count(if(`gender_id`=1,1,null)) as count1 FROM `tables` group by `device_id` order by `device_id`

$this->Table->virtualFields['count0'] = 0;
$this->Table->virtualFields['count1'] = 0;
$tables = $this->Table->find('all', array(
  'fields'=> array('Table.device_id', 'count(if(gender_id=0,1,null)) as Table__count0', 'count(if(gender_id=1,1,null)) as Table__count1'), // エイリアスにする
  'group' => array('Table.device_id'), // GROUP BYのフィールド
   'order' => array('Table.device_id'),
  'recursive' => -1, // int
));

なぜ、virtualFieldsを利用するかというと使用しないとTableのdevice_idと同じ配列に入れないためです。
集計をするためには同じ配列に入っていたほうが良いので、virtualFieldsを利用しました。

sqlのcount使う方法と注意点

sqlでcount()を使用するときに、罠にはまってしまったので、書いておきます。

[ポイント]
複数の条件でのcount()の使い方
 →if文を利用する。条件に合致しなかったときはnullにする必要がある

たとえば、以下のようなテーブル(tables)があるとします。
f:id:harucharuru:20191220144829p:plain
f:id:harucharuru:20191220150643p:plain

一つの要素でのカウント

device_idごとの数を数える場合は、次のようなSQLを実行します。
 カウントした値を入れる要素はcountとする(count(`device_id`) as count )
 device_id順に並べる(order by `device_id`)
これは問題なくできました。

SELECT `device_id`,count(`device_id`) as count FROM `tables` group by `device_id` order by `device_id`

f:id:harucharuru:20191220145059p:plain

複数要素でのカウント

では、device_idごとにgender_idがそれぞれ0と1のものの値をカウントしてみましょう。
そこで以下のように実行してみると、、、

SELECT `device_id`,count(`gender_id`=0) as count0,count(`gender_id`=1) as count1 FROM `tables` group by `device_id` order by `device_id`

f:id:harucharuru:20191220145632p:plain
count(`gender_id`=0) as count0,count(`gender_id`=1) as count1としているのに、結果が同じになってしまいました。

どうやらif文を使う必要があるようなので、使ってみます。

SELECT `device_id`,count(if(`gender_id`=0,1,0)) as count0,count(if(`gender_id`=1,1,0)) as count1 FROM `tables` group by `device_id` order by `device_id`

f:id:harucharuru:20191220145632p:plain
それでも同じ結果になってしまいました。どうやら、if文で条件文に合致しなくても0としてしまうと、数としてカウントしてしまうみたいです。
そこで、0ではなくnullにしてみます。

SELECT `device_id`,count(if(`gender_id`=0,1,null)) as count0,count(if(`gender_id`=1,1,null)) as count1 FROM `tables` group by `device_id` order by `device_id`

f:id:harucharuru:20191220150746p:plain
できました!よかった!!!!

pythonでmySQLに接続する

備忘録です。自分のメモです。

mySQL接続

#database接続
import mysql.connector
dbh = mysql.connector.connect(
        host='ホスト名',
        port='3306',
        db='データベース名',
        user='ユーザ名',
        password='パスワード',
        charset='utf8'
)
cur = dbh.cursor()

データ取得:select文

#data取得
cur.execute("SELECT `id`,`comment` FROM `テーブル名`")
for row in cur.fetchall():
    print(row[0])

cur.executeの後にselect文を書きます。データは cur.fetchall()に入っているので、一つ一つ取り出す場合はfor文を用います。
一番初めの要素(今回でいうとid)を表示する場合は、row[0]。

データアップデート:update文

    sql = "UPDATE `テーブル名` SET `要素名`=%s,`要素名`=%s,`要素名`=%s WHERE `id`=%s"
    val = (labelnum, result[1][0], str(modified), int(row[0]))
    try :
        cur.execute(sql, val)
    except :
        print('Duplicate entry for key PRIMARY')
    dbh.commit()