読者です 読者をやめる 読者になる 読者になる

Pythonを使ってTwitterのタイムラインを収集する

Python

「実践 機械学習システム」の第六章ではTwitterのタイムラインを使った感情分析を行っています。ただし英語のTweetを対象としているので、(たぶん)*1サンプルコードを実行してもあまり面白くはないのです。できることなら日本語でやりたい、というわけで自分のタイムラインからTweetを収集してみましょう。実行環境はPython3系を想定してますが、2系でも動くはずです。

基本的には↓のやり方を踏襲します。

qiita.com

必要なものは以下

  • Twitter APIの認証キー
  • PythonのOauthライブラリ(requests_oauthlib)
  • Pythonのデータ解析ライブラリ(Pandas)

Twitter APIの認証キーを取得する

Twitterのアプリケーションマネジメントサイトに行ってアプリケーションの登録を行います。

apps.twitter.com

"Create New App"から必要事項を入力していくと特に問題なく登録できるはず。最近は電話番号の登録を迫られるみたいです。営業電話でもかかってくるんだろうか。。

登録が完了したら"Consumer Key (API Key)"の欄にある"manage keys and access tokens"のリンクから先に進み、以下の4種類のキーを取得します。

これはコピペでどっかわかるところに保管しておきます。

Pythonライブラリの取得

pip使って導入。

pip3 install requests_oauthlib
pip3 install pandas

タイムラインの収集

Twitter APIでタイムラインを取得しますが、一度に取得できるTweet数の上限とAPI制限があるのでその辺と上手く付き合います。取得Tweetの上限が100件、API制限が15分に15回までとのこと。

分類器作る場合には10,000件ほどのTweetが欲しいので、パラメータで100件とってくるよう指定して、数分ごとに再取得を繰り返すようにしておきます。

CK、CS、AT、ASには先ほどコピペしたConsumer Key (API Key)、Consumer Secret (API Secret)、Access Token、Access Token Secretをそれぞれ入れておきます。

from requests_oauthlib import  OAuth1Session
import json
import time

CK = 'XXXXXXXXXXXXXXXXXXXXXX'
CS = 'XXXXXXXXXXXXXXXXXXXXXX'
AT = 'XXXXXXXXXXXXXXXXXXXXXX'
AS = 'XXXXXXXXXXXXXXXXXXXXXX'

url = "https://api.twitter.com/1.1/statuses/home_timeline.json"

params = {'count': 100}

TweetList = []

twitter = OAuth1Session(CK, CS, AT, AS)

for i in range(100):
    req = twitter.get(url, params = params)
    if req.status_code == 200:
        timeline = json.loads(req.text)
        for tweet in timeline:
            TweetList.append(tweet["text"])
    else:
        print ("Error: %d" % req.status_code)
    time.sleep(240)

4分もあればタイムラインが一巡しそうだったので、timeモジュールを使って240秒ごとに回るように指定をかけています。これを7時間ほど置いとくとTweetListにタイムラインが格納されていきます。

CSVで吐き出す

とってきたタイムラインをテキストデータとして加工したいので、Pandasを使ってデータフレームに落とし込み、それをCSVとして吐き出します。他にもやり方はありますが、型やエンコードで嵌らないのでPandasがおすすめです。

import pandas as pd

df = pd.DataFrame(TweetList)
df.to_csv('hogehoge.csv')

これで教師用データの収集はできたはず。後は発言にネガティブ/ポジティブ/そのほかのラベル貼りをやらないと。その辺は別枠で。

追記

Tweetは200件まで取れました。教えていただいてありがとうございます!

*1:実際に動かしてないのでホントのところは不明

Python3でJSONデータを解析する

Python

ググって出てくるJSON解析の方法はPython2系ばっかりなので、Python3系でのやり方をまとめます。 JSONデータは「 pythonのurllib2でjsonを取得して解析する - 文系プログラマによるTIPSブログ 」でも使われているお天気Webサービスを使います。

APIから読み込む

JSON形式のデータはWEBAPIから呼ぶことが多いかと思います。Pythonの標準ライブラリurllibとjsonを使ってAPI経由でデータを取りに行きます。

import urllib
import json

url = 'http://weather.livedoor.com/forecast/webservice/json/v1?city=400040'
html = urllib.request.urlopen(url)
jsonfile = json.loads(html.read().decode('utf-8'))

これで変数jsonfile内にデータが格納されました。jsonfileを呼び出してやるとそれっぽいデータが返ってきます。 以下はiPython環境での出力サンプルです。

In [1]jsonfile
Out[1]: 
{'copyright': {'image': {'height': 26,
   'link': 'http://weather.livedoor.com/',
   'title': 'livedoor 天気情報',
   'url': 'http://weather.livedoor.com/img/cmn/livedoor.gif',
   'width': 118},
  'link': 'http://weather.livedoor.com/',
  'provider': [{'link': 'http://tenki.jp/', 'name': '日本気象協会'}],
  'title': '(C) LINE Corporation'},
 'description': {'publicTime': '2016-04-30T16:32:00+0900',
  'text': ' 九州北部地方は、高気圧に覆われ、晴れています。\n\n 30日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 5月1日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 波の高さは、対馬海峡では30日と5月1日は2メートルでしょう。九州\n西海上では30日と5月1日は1.5メートルでしょう。豊後水道では30\n日と5月1日は1メートルでしょう。\n 福岡県の内海では、30日と5月1日は0.5メートルでしょう。\n\n<天気変化等の留意点>\n 特にありません。'},
 'forecasts': [{'date': '2016-04-30',
   'dateLabel': '今日',
   'image': {'height': 31,
    'title': '晴れ',
    'url': 'http://weather.livedoor.com/img/icon/1.gif',
    'width': 50},
   'telop': '晴れ',
   'temperature': {'max': None, 'min': None}},
  {'date': '2016-05-01',
   'dateLabel': '明日',
   'image': {'height': 31,
    'title': '晴れ',
    'url': 'http://weather.livedoor.com/img/icon/1.gif',
    'width': 50},
   'telop': '晴れ',
   'temperature': {'max': {'celsius': '26', 'fahrenheit': '78.8'},
    'min': {'celsius': '12', 'fahrenheit': '53.6'}}},
  {'date': '2016-05-02',
   'dateLabel': '明後日',
   'image': {'height': 31,
    'title': '晴のち曇',
    'url': 'http://weather.livedoor.com/img/icon/5.gif',
    'width': 50},
   'telop': '晴のち曇',
   'temperature': {'max': None, 'min': None}}],
 'link': 'http://weather.livedoor.com/area/forecast/400040',
 'location': {'area': '九州', 'city': '久留米', 'prefecture': '福岡県'},
 'pinpointLocations': [{'link': 'http://weather.livedoor.com/area/forecast/4020200',
   'name': '大牟田市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4020300',
   'name': '久留米市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4020700', 'name': '柳川市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4021000', 'name': '八女市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4021100', 'name': '筑後市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4021200', 'name': '大川市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4021600', 'name': '小郡市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4022500',
   'name': 'うきは市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4022800', 'name': '朝倉市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4022900',
   'name': 'みやま市'},
  {'link': 'http://weather.livedoor.com/area/forecast/4044700', 'name': '筑前町'},
  {'link': 'http://weather.livedoor.com/area/forecast/4044800', 'name': '東峰村'},
  {'link': 'http://weather.livedoor.com/area/forecast/4050300',
   'name': '大刀洗町'},
  {'link': 'http://weather.livedoor.com/area/forecast/4052200', 'name': '大木町'},
  {'link': 'http://weather.livedoor.com/area/forecast/4054400',
   'name': '広川町'}],
 'publicTime': '2016-04-30T17:00:00+0900',
 'title': '福岡県 久留米 の天気'}

要素ごとにアクセスしようとおもったら、パースした後の変数に引数を渡します。

In [1]:jsonfile['description']
Out[1]: 
{'publicTime': '2016-04-30T16:32:00+0900',
 'text': ' 九州北部地方は、高気圧に覆われ、晴れています。\n\n 30日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 5月1日の九州北部地方は、高気圧に覆われ、晴れでしょう。\n\n 波の高さは、対馬海峡では30日と5月1日は2メートルでしょう。九州\n西海上では30日と5月1日は1.5メートルでしょう。豊後水道では30\n日と5月1日は1メートルでしょう。\n 福岡県の内海では、30日と5月1日は0.5メートルでしょう。\n\n<天気変化等の留意点>\n 特にありません。'}

はまりどころ

Python2系のurllib2ではエンコーディング処理までやってくれていたような気がします。 Python3のurllibではデコードしないとエラーが出ます。JSONのパース時にdecode('utf-8')でデコードします。

やりたいこと

これ使って総務省API(Ver2)を上手くたたく方法模索中。

追記

Pythonの2系ではurllib2を使ってURLを読み込むのが通例でした。

import urllib
import urllib2

url = urllib2.urlopen('http://www.hogehoge.com')

python3系ではurllib2の持っていた機能がurllibに統合され、urllib.requestから呼び出せるようになっているようです。

最近読んだ本・読んでいる本

余裕がなくなってても定期的に本を読む習慣は続けたい今日この頃。最近読んだ本と読んでいる本の棚卸をしておきます。

アニメやドラマ、その他のコンテンツがなぜ人を惹きつけるのかということを探求した本。川上量生さんはぼんやりした概念をまとめることが素晴らしく上手いです。 天才クリエータとは、人を魅了するコンテンツとは何かということをまとめつつ、良質のコンテンツは普遍化し、良いクリエータは普遍化するコンテンツの中に引っかかりや別の軸を作っているという。この本はもう一回通読して自分の中で咀嚼しておきたい感じ。

コンサルタントの秘密―技術アドバイスの人間学

コンサルタントの秘密―技術アドバイスの人間学

秘密続き。この本がすこぶる読みにくくて読み進まない。書いてあること、伝えたいメッセージはわかるものの読むのがつらい。物理本(書籍)という制限もあって空き時間に読めないのもつらい。読書継続中。

コンサルタントの道具箱

コンサルタントの道具箱

とはいえ尊敬するベンチャー社長の人がお勧めしてて、ちょっと読んだだけでも知見を得られることはわかったので何とか慣れたい。こういう時には同じ著者の簡単な本から読むのが良いと思ってるので、ワインバーグ氏の電子書籍も並行して読んでおります。こっちは個人的に結構読みやすい。コンサルタントの道具箱はおそらく「コンサルタントの秘密」の要約版なので、こちらの本からぼちぼち攻めて行こうと思います。電子書籍なのでいつでも気軽に読めますし。

3月に入れば若干仕事の余裕・心の余裕が出てくるといいなあ。

近況

仕事が色々積みあがっててココロボで遊ぶのも、機械学習を手掛けるのも何も進んでおりません。やることが増えるとパフォーマンスが落ちてくるのは知ってたので、再度GTDの教本を読みつつ何とかしようとしてる今日この頃。

はじめてのGTD ストレスフリーの整理術

はじめてのGTD ストレスフリーの整理術

最近社内の活動として、オープンソースの利用を推進しようとしていたり。地理空間系の業界ではOSSで出来ることが結構多くて(というか普段の作業はOSSで賄えるので)、作業を効率的にやるためにもOSS普及させたいなと考えています。

地理空間系のOSSはFOSS4Gと言われますが、この導入マニュアルと書籍ライクな形にして社内に波及させていければと。可能であれば世の中にも共有できればと。OSSで得たものはOSSに返す的な。

しかしGISに関わってたかが数年。まだまだつまるところが多いなあ。MapServer系の話やタイルづくりのところが全然理解できない。。

続【未完】シャープ製お掃除ロボット(cocorobo RX-V200)のAPIを叩く

cocorobo 電子工作

続編ですが未完です。前回はこちら。

quzee.hatenablog.com

API叩いたら変なエラーが返ってきたというのが前回までのあらすじでした。問い合わせてみたところ「もっかい初期化してみて」というお返事をいただいたので再度初期化して再設定しました。結果該当のAPIエラーはなくなったという。担当者の方すいません。初期化&再設定という最も根本的な解決方法を試してませんでした。

というわけでちゃんと動くようになったのでAPIを叩く作業を再開したいと思います。

音声発話APIを叩く

どっちかというと使いたいのは音声発話APIなのでそっちを叩いてみます。発話APIはエンドポイントのURLが違うだけ。前回と同じくcurlで叩く。

curl -H 'Content-Type: application/Json' -d '{"apikey_cocorobo":"XXXXXXXXXXXXXXXXXXXXXXXX","message":"XXXXXXX"}' 'https://developer.cloudlabs.sharp.co.jp/cloudlabs-api/cocorobo/speech'

これでいけると思ったんですが、以下のエラーが返ってきます。

{"resultCode":"1","errorCode":"E010202","message":"Request Parameter Not Found."}

よくわからん。以下はトラブルシューティング的なやつと、上記エラーを検証したやつです。

APIのレスポンスが無い場合

前回のエントリにコメント頂いた「API叩いたのに返ってこない場合」のトラブルシューティングです。

cocorobo APIはヘッダーを引き渡さないといけませんが、大文字・小文字をちゃんと記載してないと何も返ってきません。前のエントリでは'Content-Type: application/json'となってますが、jsonの一文字目を大文字にしていただけるとたぶん通ります。

駄目なやつ

curl -H 'Content-Type: application/json' -d '{"apikey_cocorobo":"XXXXXXXXXXXXXXXXXXXXXXXX"}' 'https://developer.cloudlabs.sharp.co.jp/cloudlabs-api/cocorobo/auth'

大丈夫なやつ

curl -H 'Content-Type: application/Json' -d '{"apikey_cocorobo":"XXXXXXXXXXXXXXXXXXXXXXXX"}' 'https://developer.cloudlabs.sharp.co.jp/cloudlabs-api/cocorobo/auth'

とはいえレスポンスが返ってくるってだけで"errorCode":"E010202"は回避できません。

検証作業

エラーメッセージを読むと「パラメータが無い」とのことなので、ローカルホストにサーバを立てて各種パラメータを渡せているかどうかを検証します。 @aramoto さんにいただいたプログラムを使わせてもらいました。

【娘が泣き始めたので続きは明日書く!!】

【未完】シャープ製お掃除ロボット(cocorobo RX-V200)のAPIを叩く

電子工作 cocorobo

ココロボは優秀な家庭用ロボだと公言しつつ、公式アプリからしか制御できないのでハックし甲斐がねえなと思って早幾年。8月26日にシャープから開発者向けAPIが公開されました。これ公開するまでに色々あったんだろうなあ(社内調整が)。

一個問題があってうまく動かせてないですが、備忘録的にAPIの叩き方を記録します。

APIの概要

今回公開されたAPIはWebAPIとアプリAPIの二種で、それぞれできることが違います。

  • WebAPI

    • 認証
    • 音声発話
  • アプリAPI

    • 機器制御
    • 機器情報の取得

何をやるにしてもWebAPIの認証をかける必要がありますが、そこでこけているのでこの記事は未完です。単なる作業記録。 ちょっと残念なのが、機器制御や情報取得がアプリAPIAndroid APK)の使用を前提としていること。機器制御に関しては法的な問題があるかも…と思う節もあるけれど、ココロボの情報取得だけだったら問題ないんじゃねえのかな。

ココロボは温度・湿度、電池残量、衝突回数などを取得しているので、そのデータをWebAPI経由で取れたら良いと思うんです。公開しない理由が良く分からない(APIのメイン開発者が辞めたとかだったらしゃーないけど)

WebAPIの叩き方

公式サイトのリファレンスにはサンプルコードがありますが、JavaPHPのサンプルだけでした。両方そんなに使ったことないので、UNIX系で汎用的につかえるcurlAPIを叩きます。

curlMac OSLinux系なら大概デフォルトで入ってます。今回はRaspberry Pi(Rasbian)使いました。

curl -H "Content-type: application/json" -d '{"apikey_cocorobo":"XXXXXXXXXXXXXXXXXX", "message":"ほげほげ"}' 'https://developer.cloudlabs.sharp.co.jp/cloudlabs-api/cocorobo/auth' 

JSONで投げます。apikey_cocoroboの部分は開発者登録をした際に割り振られるキーです。

POSTで渡せと書いてますが、-dオプションがデフォルトでPOSTなのでこれで大丈夫。なんだけど。。

{"resultCode":"1","errorCode":"E010106","message":"Registertd MAC Address:XXXXXXXXXXXXX different with COCOROBO MAC Address."}

なんかMACアドレスが違うらしい。というわけで一旦ここまで。シャープに問い合わせて回答もらえ次第つぎの作業に移ります。せっかく勉強しているのでPythonで制御したいなー。

developer.cloudlabs.sharp.co.jp

Pythonでフォルダ・ファイルを操作する(ファイル取得・フォルダ作成など)

Python

単純作業を効率化するためにPythonを使います。フォルダ自体や、中に含まれるファイルの操作をサクサク行う寸法よ。

続きを読む