まいにち右往左往

日記です。興味の範囲がバラバラで統一性がない日記です。だんだん備忘録っぽくなってきました。

Pythonで雪が降ってたらLINEに通知を出してみる その1 Twitterからの画像の取得

冬ですね。突然ですが私が住んでいるのは長野県です。長野県の冬といえば、困るのが雪です。朝起きて、さて出勤しようかとドアを開けたとき、雪が積もっていればそこで遅刻確定です。なにしろいつもギリギリで生きていますので。

まあそんな雪国ですので、以前とある場所にウェブカメラを設置しました。職場から遠い人でも、職場の様子がわかるように、です。
雪が降ったら雪かきにこい、ということなのです。

 

これはなかなかいいものでした。布団の中にいながら、職場の様子がわかるので。

 

ですが、たまにうっかりしてしまうんですよね。天気予報が雪と言っていないのに降るときもあるからです。そして、能動的に確認をしなければいけないのです。今年も、12月の中頃に少しだけ雪が降ってひやりとしました。幸いなことに、遅刻はせずに済みましたけれども。

 

ただこういう本質的でないところに神経を使って生活するのは、好きなことではありません。ですので、最近かじっているPythonを使って、雪が振っていそうならLINEに通知が来るようにしてみました。

 

前提条件

既設のウェブカメラですが、RaspberrypiとUSBカメラでできています。1時間ごとに撮影しTwitterへ撮影時刻、撮影場所等のテキストをくっつけて投稿しています。いろんな場所におき、一つのアカウントからtweetしています。

 

処理の流れ

今回の流れですが、次のようになりました。

  1. まずはTwitterから写真をダウンロード
  2. Pythonで標準的な写真(晴れた日のやつです)と特徴点マッチングで比較
  3. 類似度が一定の基準を下回ったら(晴れた日と異なってたら)LINEで通知

3番ですが、比較するのは夜のみです。昼間雪が降ってもそりゃさすがにわかりますし。出勤前日の夜に通知がくれば心に余裕ができますし、降り始めてからの通知でも同様です。あとは、昼間の写真だと情報量が多すぎてちょっと処理がめんどくさそうというのもあります。雲の違いとかも拾ってしまいそうで。

 

Twitterからの画像の取得

今回は、まず処理1のTwitterからの画像の取得についてです。例によって例のごとく、先人の方々の知恵もお借りします。

qiita.com

 

Raspberrypiから写真をtweetする際にもお世話になりました。まあ今回はその逆で、tweetから写真をダウンロードしたい訳なのです。まずはtweetから写真のリンクを抜き出してみます。

 

あんまりリファレンスとかと異なるところはないのですが、今回はTwitterのユーザー、tweetする時間、内容も以前自分で設定したものに合わせているので、汎用性の低い内かもしれません。

まずは、ユーザーIDを指定し、countで取得するtweetの数を指定します。複数の機器からtweetしてるのですが、時間がも若干異なる設定になっており、今回は3つも取得すればその中に1つ目的のtweetがはいっているのです。

 #取得するユーザーのIDと取得するtweetの数の指定
    params = {
            'user_id': 取得したいユーザーのID, 'count': 3
            }

 

tweetjsonとして取得できるので、その中から必要なものを取り出します。が、いらないtweetもあるので、取得した3つのtweetの中から、お目当てのものを抜き出します。それには、tweetに含まれる撮影場所に欲しい場所が含まれているかで判断します。

for tweet in timeline:
        text = tweet['text']
        #tweetに含まれる撮影場所で絞込
        if 'tweetに含まれる撮影場所' in text:
            urls = tweet['entities']['media']
            mediaURL = urls[0]['media_url']
            return mediaURL

 

これで写真のURLが取得できたので、ダウンロードするだけです。

import urllib.request
import os
import datetime

def downloadPic(URL):
    #雪判別用の写真は一回使えればいいため、前回のファイルを削除
    os.remove('pic.jpg')
    urllib.request.urlretrieve(URL,'pic.jpg')

 

今回は単純に晴れた日の写真と比較して、雪が降っているかを判別できればいいので、取得した写真を取っておく必要はありません。ただ、検知率が低ければ別の方法を考えなければいけないので、その時のために写真は個別に保存することにします。

    month = str(datetime.datetime.now().month)
    day = str(datetime.datetime.now().day)
    hour = str(datetime.datetime.now().hour)
    filename = r'保存させたいパス' +'\\'
    filename =  filename + month +  day + hour +'.jpg'
    urllib.request.urlretrieve(URL,filename)

 

名前が被らないように取得時の月日時間.jpgみたいにして保存させました。検出率が低かったり過剰に検出しちゃうようなら、こうやって集めたデータを使って今度こそ機械学習に進むべきなのかもしれません。

 

まとめると、こんなコードで運用しています。

import json
from requests_oauthlib import OAuth1Session


def getMediaURL():
    Consumerkey = 'Twitterで発行したConsumer Key'
    ConsumerSecret = 'Twitterで発行したConsumer Secret'
    AccessToken = 'Twitterで発行したAccess Token'
    AccessSecret = 'Twitterで発行したAccess Secret'
    
    #tweet取得用APIのURL
    URL='https://api.twitter.com/1.1/statuses/user_timeline.json'

    Twitter = OAuth1Session(Consumerkey, ConsumerSecret, AccessToken, AccessSecret)
    
    #取得するユーザーのIDと取得するtweetの数の指定
    params = {
            'user_id': 取得したいユーザーのID, 'count': 3
            }
    
    req=Twitter.get(URL, params = params)
    timeline = (req.text)
    timeline = json.loads(req.text)

    for tweet in timeline:
        text = tweet['text']
        #今回は特定の場所の写真のみを使いたかったので、tweetに含まれる撮影場所で絞込
        if 'tweetに含まれる撮影場所' in text:
            urls = tweet['entities']['media']
            mediaURL = urls[0]['media_url']
            return mediaURL

            
import urllib.request
import os
import datetime

def downloadPic(URL):
    #雪判別用の写真は一回使えればいいため、前回のファイルを削除
    os.remove('pic.jpg')
    urllib.request.urlretrieve(URL,'pic.jpg')

    #今回の件とは別に機械学習に使えるかもしれないので、個別に名前を付けて保存
    month = str(datetime.datetime.now().month)
    day = str(datetime.datetime.now().day)
    hour = str(datetime.datetime.now().hour)
    filename = r'保存させたいパス' +'\\'
    filename =  filename + month +  day + hour +'.jpg'
    urllib.request.urlretrieve(URL,filename)

downloadPic(getMediaURL)

 

 

現在仮動作中です。あいにくと今夜は雨でしたが、一応晴れとは違うということで通知はバンバンきています。本当に雪になった時にも、ちゃんと通知がきてくれるといいのですが。こればかりは天候なので、ゆっくり待つしか……あれ?雪が若干楽しみになってきたような??