ひとメモ

主にプログラミングのメモ

ツイート履歴をpandasでcsvファイルに書き出し→読み込みするとズレる問題

www.hitowaft.work

上の記事に関連して小ネタを一つ。

ツイート履歴(tweet.jsから読み込んだもの)を編集した後に、再度csvファイルに書き出し(pandasのto_csv)、その後pd.read_csv()で読み込んだデータで、以下写真のようにnaが増えてしまうことがありました。

print(original_data.isnull().sum())
print(reloaded_data.isnull().sum())
f:id:hwhw:20200512132305p:plainf:id:hwhw:20200512132311p:plain

その場合は書き出す際にline_terminatorを以下のように指定すればOK。

df.to_csv('tweet_data.csv', index=False, line_terminator='\r\n')

twitterのデータをダウンロードしてpandasで読み込みたい

ツイート履歴をpandasで扱いたい

以前はcsv形式でツイートデータがダウンロードできていましたが、今はjsファイル等で提供されています。(2020年5月11日現在)

pd.read_jsonで読み込むだけではネストされた内容がひと塊りになってしまうので、一工夫する必要がありました。

なお以下のコードでも、まだ一部ネストされたままデータフレームに読み込まれますが、その辺は自力で何とかしてください。

前処理

tweet.jsファイルを開き、冒頭のwindow.YTD.tweet.part0 = [ という部分とファイル最下部の]を消しておきます。

コード

import pandas as pd
from pandas.io.json import json_normalize

tweet_data = pd.read_json('/tweet.js')

df = json_normalize(tweet_data.to_dict('records'))

df.head()

GitHubにnotebookを置いておきます。

github.com

参考

https://oku.edu.mie-u.ac.jp/~okumura/python/tweetdata.html

外出できなくなったので完全食を注文した(BASE FOOD)

以前から気になっていたBASE BREADとBASE PASTAを買いました

完全栄養の主食 BASE FOOD スタートセット

きっかけ

はい。これはもしやコロナ…?たぶん外に出たらあかんやつや…。
というわけで二週間の自己隔離の始まりです。

ここ最近買い物に行った際は普段より多めに食料を買うようにしてましたが、ちょうどそろそろ買い物に行こうというタイミングでした。困る。

外に出られないとしても、ちゃんと栄養を摂りたい!ということで買いました。
今は宅配の荷物をドアの前に置いてくれて、人に会わず受け取れるのがいいですね。

*なお、味覚については次の日に回復しました。やや微熱が残るのみ。

味など

ここでは書いてないけどCOMPと比べての話です。

精製した小麦などと違って血糖値が急激に上下しない(食後に眠くなりにくい)のが嬉しいですね。

あとオメガ3脂肪酸がちゃんと摂れるのが地味に嬉しい。

ベースパスタの方はまだ食べてないです。楽しみ。

呼吸が浅くなりがちなのでMi Band3に深呼吸を促すリマインダが来るようにした

先日XiaomiのMi Band3を買いました。

www.hitowaft.work
スマホとBluetoothで接続して、LINEやTwitter、その他様々なアプリからの通知を確認することができます。

1時間座りっぱなしでいると「動きましょう」と通知してくれる機能は元々あるのですが、せっかくなのでもっと自分向けの通知を作って受け取ってみたいと思います。

使ったもの

手順

  1. LINE Notifyに登録してアクセストークンを取得する
  2. GASに後ほど記載のコードを貼り付けて、文言を好きに編集する
  3. GASでスクリプトのプロパティにACCESS_TOKENを登録する(省略可・後述)
  4. GASのトリガーをセットして、お好みの間隔で通知を受け取る

LINE Notifyのアクセストークン取得時の注意事項

LINE Notifyのアクセストークンを取得する際は、トークン名を一文字にしておきます。名前が長くなると、その分文言が入るスペースがなくなってしまうので…。

また、LINEのグループを作成してそこにLINE Notifyを招待し通知を受け取るやり方もあるのですが、そうすると[グループ名][LINE Notify]文言という形で通知が来て、ほぼ画面が埋まってしまうため1:1でLINE Notifyから通知を受け取るを選択します。

コード

function myFunction() {
  var messages = ["深呼吸しよう", "背筋を伸ばそう", "hoge", "fuga", "foo", "bar"];
  var random_num = Math.floor( Math.random() * messages.length );
  sendHttpPost(messages[random_num])
}


function sendHttpPost(message){
  token = PropertiesService.getScriptProperties().getProperty("ACCESS_TOKEN")

  var options =
   {
     "method"  : "post",
     "payload" : "message=" + message,
     "headers" : {"Authorization" : "Bearer "+ token}

   };

   UrlFetchApp.fetch("https://notify-api.line.me/api/notify",options);
}

コード解説

特に難しいことはしてませんが、JSやGASに不慣れな人に向けて少し解説します。
messages変数に通知したい文言を配列として入れています。
この配列の中から、実行ごとにランダムで一つ選ばれた文言がトリガーで決めた間隔で通知されます。

各文言を、全角なら13文字・半角なら34文字までに抑えると画面からはみ出しません。

token = PropertiesService.getScriptProperties().getProperty("ACCESS_TOKEN")の部分では、GASでスクリプトのプロパティに登録した値を取りにいってます。
どこにも公開しないならtoken = "LINE Notifyで取得したトークン"みたいにベタ書きでもいいかな。

動かないなと思ったら上部にある関数を選択からmyFunctionを選んで実行してください。


こんな感じで通知が来ます。
[良]となってるのが、トークン取得時につけた名前です。何かいい意味の漢字が良いなと思ったけど、特に思いつかなったのでそのまま良にしました。

参考リンク

Google Apps ScriptからLINE NotifyでLINEにメッセージを送る - Qiita

【超便利&お手軽】Python + LINE NotifyでLINEメッセージ送信 – Blue-black.ink

Xiaomi Mi Band3を買ったのでレビュー

安価なスマートウォッチ Mi Band3を買いました

Amazonで3700円で買いましたが、今見たら3100円になっていた…。
(2020年1月30日追記:3000円切る値段になってました。Mi Band4も出てるみたい )

写真はちょっと着ける位置が間違っていて、本当は手首の出っ張った骨より腕側に着けます。

良かったところ

通知を逃す心配がない

スマホとBluetoothで接続していて、通知が来ると振動します。
スマホをポケットに入れてても歩いてると振動がわからなかったりしますが、腕だととてもわかりやすいです。
何かの連絡を待つような時でも、スマホ本体はカバンにしまって安心していられます。

特に良いのがロック画面に出してない通知も、ちゃんと届くというところです。
Twitterの通知とか、人に見られたくないので通知センターのみの通知にしてるんですよね。それが腕に届くので、便利。

電池の持ち

睡眠時に心拍数を測る設定(睡眠ログの精度が良くなるらしい)にすると電池のもちが悪くなるということでしたが、約2週間もちました。
あんまり充電のこと気にしなくて良いのは素敵。
なおスマホの方がBluetoothをつけておく分電池の減りが少し速くなりました…。

Slackの通知が見れて嬉しい

仕事中非常に単純な作業ばかりしているので、脳のリソースが余っています。
そこにSlack(チャットツール)の通知が来ると、みんななんか話してるなーとちょっと楽しい気持ちになります。(画面が小さいので話してる内容はほぼわからない)

常に腕に時計が着いてると便利

腕時計は良い。

期待したほどでもなかったところ

まとまったデータの取得が面倒

そもそも睡眠のトラッキングをしたくて買ったのですが、そのデータをまとめて取得するのが面倒でした。
ログ取得のリクエストを送信→メールで用意できた旨の通知が来る→ダウンロードページにログインしてデータを取得という形。
毎日のデータはアプリ内で見られるので、自分でデータを弄りたい人以外には十分だと思います。

睡眠ログはまあまあ

私は早朝覚醒が多いのですが、目が覚めてもそんなに動いたりするわけではないのでその時間は中途覚醒として拾えていないことが多いです。
それ以外はスマホの睡眠トラッキングアプリよりは正確かなぁという気もしますが、正直よくわかりません。

座りすぎ通知の精度が低い?

1時間座りっぱなしでいると振動でお知らせしてくれる機能がありますが、役立つこともあればしばらく座っていた後立ち上がって動いてるのに「動きましょう」と知らせてくれることもあります。
「もう動いとるでw」と思うだけですが。

まとめ

この値段だし、時計も欲しかったので「買って良かったなー」という感じ。

hwhw.hatenablog.com

複数の環境変数をまとめて取得したい(Python)

やりたかったこと

qiita.com

上記の記事を参考にスクレイピングの練習をしていたところ、次のような部分がありました。

URL      = "https://qiita.com/login" 
ID       = ""                        
ID_sel   = "#identity"               
PASS     = ""                        
PASS_sel = "#password"               
Selector = ".st-Header_loginUser img"

私は完成したものを公開したい等諸々の理由で、上記全ての変数を環境変数としてos.getenv()で取得する形にしようと思いました。
同じ形が続くのでforループにします。

複数の変数に環境変数の値を代入

初めは次のような形でやろうとしましたが、これだと変数が未定義だというエラーが出ます。

Pythonはvar hoge = ~のように変数を宣言しないので、先にリストにしておくということができませんでした。

ダメコード

conf = [URL, ID, ID_sel, PASS, PASS_sel, Selector]

for i in conf:
    i = os.getenv(str(i).upper())

NameError: name 'URL' is not defined こんなエラーが出ます。
なので、以下のように書き換えたら動くようになりました。

動くコード

conf = ["URL", "ID", "ID_sel", "PASS", "PASS_sel", "Selector"]

for i in conf:
    locals()[i] = os.getenv("{}".format(i.upper()))

まず変数名をstrとしてリストを作っておきます。

次にlocals()を使います。
これは辞書形式でローカル変数を返してくれるそうで(よくわからない)、[i]がキーで変数名、os.getenv("{}".format(i.upper()))が値で各環境変数になります。
upper()としているのは環境変数を大文字で保存しているため。)

余談

書いといてなんですが、普通はこういう時わざわざループさせないのかもしれないなぁと思いました。
でも思った通りに動いて嬉しかったのでメモ。

DockerアプリのHerokuへのデプロイをGitLab CIを使って自動化する

GitHubにpushするだけでHerokuにデプロイできるようになった

Dockerでwebアプリを作成し、それをHerokuにデプロイする際

$heroku container:push web
$heroku container:release web

という感じで、手元でビルドしたイメージをHerokuのContainer Registryにpushしていました。(公式ドキュメント

それだと時間がかかるのと、CI(Continuous Integration:継続的インテグレーション)というのを使ってみたかったので、GitLab CIを試しました。

その結果Git Hubにgit pushするだけで、修正した部分が自動的に反映されるようになりました。便利〜。

なお時間は同じかそれ以上にかかります。
でもPCつけたまま待たなくて大丈夫なのが良い。

関連記事 hwhw.hatenablog.com

手順

※Dockerfile等の説明は割愛します。

  • GitLabのアカウントを作成→GitHubと連携

  • プロジェクトのルート直下に.gitlab-ci.ymlというファイルを作成

  • HerokuのAccount Settings(アプリのSettingsじゃなくて画面右上の)でAPI Keyを取得

  • GitLabのSettings > CI/CD > Variablesで環境変数を設定

    • HEROKU_TOKEN = 上記のHeroku API Key
    • HEROKU_APP = Herokuのアプリ名
  • GitHubにpush → 自動でデプロイ!嬉しい!

.gitlab-ci.yml

そのままコピペで多分動きます。詳しく解説できるほど理解はしてない…。

push-heroku:
  only:
    - master
  image: docker:stable
  services:
    - docker:dind
  script:
    - echo $HEROKU_TOKEN | docker login --username=_ --password-stdin registry.heroku.com
    - docker build -t registry.heroku.com/$HEROKU_APP/web .
    - docker push registry.heroku.com/$HEROKU_APP/web

    - docker run --rm -e HEROKU_API_KEY=$HEROKU_TOKEN wingrunr21/alpine-heroku-cli container:release web --app $HEROKU_APP

参考リンク

ほぼQiita記事のymlファイルまんまですが、それだけだとheroku container:release webの部分が自動でできなかったのでもう一つのリンクを参考に全自動にしました。

HerokuのContainer RegistryベースのデプロイをGitLab-CI上で行う - Qiita

Release container to heroku with Gitlab.ci - Qrated - Medium