自動化厨のプログラミングメモブログ │ CODE:LIFE

Python/ExcelVBA/JavaScript/Raspberry Piなどで色んなことを自動化

GASとSlackとGoogleHomeで毎朝なにを着れば良いか教えてもらう

f:id:maru0014:20181014232943p:plain

最近は季節の変わり目で朝起きて寒いなーと思って上着を着ていくと、意外と昼間は暑くて上着が邪魔になったり。逆に意外と寒かったり。

朝どんな服装にするべきか悩ましいのですが、tenki.jpではどれくらいの服装なら体感温度が適温になるのか「服装指数」というものを表示してくれています。

これを毎朝確認すれば前述のような自体は避けられる!と思ったが自動化厨にとってそれは大変面倒くさいというもの。

今回はGASでお手軽にスクレイピング→Slackへ投稿→GoogleHomeに喋らせるという仕組みを作りました。

※今回の記事では「GASでスクレイピング→Slackへ投稿」までを紹介します。「→GoogleHomeに喋らせる」は以下の過去記事を参照ください。

code-life.hatenablog.com

Googleスプレッドシートでスクレイピング

東京地方(東京)の服装指数 - 日本気象協会 tenki.jp

https://tenki.jp/indexes/dress/3/16/4410/

東京の方はこちらのページですね。お住まいの地域に合わせてページURLをコピーしておきましょう。

このページに欲しい情報は全て載っています。

  1. 服装指数
  2. どんな服装にすべきかのコメント
  3. 天気
  4. 最高/最低気温

これらの情報をスプレッドシート上に取得・表示できるようにするのですが、Googleスプレッドシートには超便利な関数「importxml」があります。

この関数は=importxml("スクレイピング対象URL","XPathクエリ")のように記述するだけで対象要素のテキストをセルに表示することができます!

スプレッドシートの完成イメージ

f:id:maru0014:20181014234349p:plain

だいたいこんなかんじです。ぶっちゃけ3行目以下は不要なんですが、なぜかXpathのインデックス番号を指定しても全部取得されちゃってめんどくさいので諦めてこのまま使いました。

関数入力

各項目を以下のようなXpathで取得します。

※今回スクレイピング対象URLはI1セルに入力してあります。

項目 関数入力
A 日付 =today()
B 指数 =importxml(I1,"//*[@id='main-column']//*[contains(@class, 'indexes-telop-0')]")
C 天気 =importxml(I1,"//*[@id='main-column']//*[@class='weather-telop']")
D 最高気温(℃) =importxml(I1,"//*[@id='main-column']//*[@class='high-temp']")
E 最低気温(℃) =importxml(I1,"//*[@id='main-column']//*[@class='low-temp']")
F 降水確率 =importxml(I1,"//*[@id='main-column']//*[@class='precip']")
G コメント =importxml(I1,"//*[@id='main-column']//*[contains(@class, 'indexes-telop-1')]")
H 文章 =CONCATENATE("本日の天気は",C2,"、最高気温",D2,"、最低気温",E2,"、降水確率",F2,"%、服装指数は",B2,"です。",G2,"。")

H列にはSlackへ投稿させるメッセージ内容です。各項目を文章として結合しています。

以下を参考にしました

review-of-my-life.blogspot.com

qiita.com

GASでスプレッドシートのデータを取得してSlackへ投稿

Slackで事前に着信Webフックを用意しておきます。以下の過去記事を参考に設定してください。

code-life.hatenablog.com

コード.jsに以下のように記述

var postUrl = 'ここにSlackの着信WebフックURL';

function myFunction() {
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet(); //スプレッドシートを取得
  var sheet = spreadsheet.getActiveSheet(); //シートを取得
  var message = sheet.getRange("H2").getValue(); //投稿用文章が入っているセルの中身を取得
  
  var payload = JSON.stringify(
  {
     "text" : message
  });
  
  var options =
  {
    "method" : "post",
    "contentType" : "application/json",
    "payload" : payload
  };
  
  UrlFetchApp.fetch(postUrl, options); //Slackへ投稿
}

ここまでできたらテスト実行。再生ボタンを押しましょう。

f:id:maru0014:20181015000147p:plain

これでSlackへ無事投稿されればOK。

毎朝自動実行する

再生ボタン左にある時計アイコンをクリック。

以下のように設定して保存すれば毎朝教えてくれます。

f:id:maru0014:20181015000336p:plain

Docomoのsimロック解除済みGalaxy Note8 SC-01Kをソフトバンク回線で使ってみた。方法と注意点

www.nttdocomo.co.jp

まず結論から言うと問題なく使えた。

前提条件

  • simロック解除済みのGalaxy Note8 SC-01Kをヤフオクで購入
  • ソフトバンクsimカードはAndroid端末用のためIMEI制限がかかっている

使用状況

  • 通話利用可能
  • SMS利用可能
  • 通信品質問題なし
  • S!メール(ソフトバンクのメールアドレス)利用可能
  • Wi-Fiテザリング可能

注意事項(ソフトバンクのお客様サポートページは必読)

www.softbank.jp

※記事執筆時点と異なる内容の場合がありますので必ず現時点の情報をご確認ください。

① simロックが解除されていない端末は利用できません

当然ながらsimロックが解除されていないスマートフォンは利用できません。

Galaxy Note8がソフトバンクからも発売されていたら何も問題なかったのですが、残念ながらDocomoとauからしか発売されておらずこの度の状況になりました。 当然ですがDocomoやauの端末をそれら以外の会社で使おうとすればsimロック解除が必須となります。

メルカリやヤフオクなどで購入する場合は必ずロックが解除されたものを選びましょう。

続きを読む

Raspberry PiのセットアップからPython実行環境構築とイメージファイルバックアップまで

Raspberry Piを購入してから10ヶ月ほど経ちましたが、分からないなりに色々いじくり回していると余計に訳がわからない事態に陥ることもしばしば。

仕方ないクリーンインストールするか・・・ということが何度もありました。

その手間をなるべく省くために大まかなセットアップ手順とリセットを楽にするためのimgバックアップの方法をメモしておきます。

  • Raspberry PiのRaspbianセットアップと設定後イメージファイルのバックアップ
    • ①OSのイメージファイルをダウンロード
      • どちらを選べばいいのか
    • ② EtcherでSDカードに書き込む
    • ③ 起動後すぐにSSH接続できるように設定しておく
      • Wi-Fi設定
        • 最新版では一度有線接続してセットアップが必要かも
      • SSHの有効化
    • ④ Raspberry Piにセットして起動し、SSH接続
      • 有線LANで直接接続する場合
      • 無線LANでする場合
    • ⑤ raspi-configで各種設定
      • 1 ChangeUser Password
      • 3 Boot Options・・・起動方法
      • 4 Localisation Options
      • 5 Interfacing Options
      • 7 Advanced Options
    • ⑥ IPアドレスを固定する
  • こだわり設定
    • ①「SDカード寿命対策」
      • 1. Swap領域の無効化
      • 2. テンポラリ領域 を RAM へ
      • 3. rsyslog の ログ出力を抑制
      • 4. ログ出力ディレクトリ を RAM へ
    • ② 軽量化・高速化
      • 1. カーネルのログを抑制
      • 2. CPU の 動作クロック設定
      • 3. アップデートやらクリーンアップやらをshファイルで一括実行
  • イメージファイルのバックアップ
  • Python実行環境を整える
    • git経由でpyenvをインストール
    • 依存関係のあるライブラリをインストール
    • pipenvをインストール
    • pipenvでプロジェクト単位の仮想環境構築
    • 仮想環境でHello World!
      • pipでパッケージをインストールするには
      • 別の仮想環境に切り替える
  • あとがき

Raspberry PiのRaspbianセットアップと設定後イメージファイルのバックアップ

NOOBSが書き込まれたSDカードが付属しているパターンならそれを使ってもいいと思います。

①OSのイメージファイルをダウンロード

RASPBIAN

www.raspberrypi.org

RASPBIANにはDESKTOP版とLITE版の2種類が用意されています。

DESKTOP LITE
容量 4.49GB 1.73GB
UI GUI / CLI CLIのみ

GUI・・・グラフィックユーザーインターフェース。Windowsのようにマウスを使って視覚的、直感的な操作。

CLI・・・コマンドラインインターフェース。マウスなどは使わずキーボードでのコマンド入力のみで操作。

どちらを選べばいいのか

CLIでの操作に慣れていない場合やSDカードの容量に余裕がある(8GB以上)場合はDESKTOP版。

とりあえず手持ちの古いSDカード(4GB)などで安く済ませたい、Raspberry Pi Zeroなのでスペックが低いという場合はLITE版。

※DESKTOP版も設定で後からCLIに切り替えることが可能です。

続きを読む

Google HomeをPythonで自在に喋らせてみた(VoiceTextを使ってるので声も選べます)

f:id:maru0014:20180923220401p:plain

昨年末から愛用してきたGoogle Home Mini。

手に入れて最初にやったのがNode.jsの「google-home-notifier」で色んな通知を喋らせるというもの。

しかし、自分のjavascriptの知識なんてjQueryでウェブサイトに動きをつけて遊んだりする程度。よくわからないまま先人の知恵たるブログを参考にして実装しましたが、仕組みがよくわからなくてモヤモヤしていました。

でもようやく出来ました!Pythonで!これを「google-home-notifier-vt」と名付けます。

  • できるようになること
  • 参考にした記事
  • 改良点
    • Voice Text API対応
    • slackの特定チャンネルに投稿したら喋る
    • 文字化け対策
    • 謎の空白対策
  • コード全文
  • 導入手順
    • ① 各種ライブラリをインストール
      • python-voicetextのインストールでエラーが発生した場合
    • ② ngrokの準備
      • インストール
      • ユーザー登録・認証
    • ③ VoiceText APIユーザー登録
    • ④ Slackのチャンネルと着信Webフックを用意
    • ⑤ Pythonコード編集
    • ⑥ 実行
      • SSHで実行する場合
    • ⑦ Slackの発信Webフックを用意
      • その他オプションなど
  • あとがき

できるようになること

  • Slack→ngrok→Raspberry Pi→VoiceText→Google Homeを喋らせる
  • 声や読み上げ速度を選べる(Voice Text API)

参考にした記事

このQiita記事を見てこれはやれる!と思いました。

Pythonを使って、Google Homeに喋らせてみる - Qiita

決定打はこれ。Flaskで作られていますが素晴らしい出来栄え。

Chromecastデバイスに喋らせるPython スクリプト · GitHub

最初はBottleで自分なりにやってみたもののキャストしたあとの遅延が長くて3日間くらい悩みましたが、Slash Nephyさんのようにファイル名を時間から出力してユニークなものにすることで多分解決?

そして楽したいのでそのままFlaskでやります笑

続きを読む

Pythonのスコープ(変数の参照・代入可能範囲?)でつまづいた。グローバル変数を関数内で変更するには

今日Flask-ngrokというライブラリを使っていてつまづいたので戒めメモ。

Pythonのグローバル変数は関数内で代入できない

num = 0

def num_func ():
    num = 1
    print("num " + x)

このように実行したときにてっきりnum 1と表示されると思っていましたが、表示されたのはnum 0でした。

実はPythonのグローバル変数は関数内で参照はできるが、変更はできないらしいです。

困った・・・。と調べていたらありました。

【Python】ローカル変数とグローバル変数 | アルゴリズム雑記

関数内でglobal宣言すれば代入可能

num = 0

def num_func ():
    global num 
    num = 1
    print("num " + x)

関数内で代入したい変数名の前にglobalと付けて宣言したあとなら関数内で代入可能らしい!

やっぱりこういう基礎的なところすっ飛ばして動くもの作ろうとするとちょいちょいつまづきますね笑

でも真面目に基礎やるのが嫌いなので走りながら勉強します。