1時間おきにブログ記事を自動で呟けるようにした話

前回の課題を解決しましたので、簡単に共有。

前回やったこと

  • 決まった時間にツイート
  • 定期的に自動フォロー

この2つをPythonとherokuで作りました。詳細は以下記事。

前回の課題

上手いこと定期実行出来たのはいいんですが、3つほど課題が残りました。

  • よく考えたらherokuの時間指定アメリカだから意味わからない時間に実行しているのでは
  • 毎回まとめてツイートしちゃうのどうにかしたい
  • 検索で引数2つしかとれないの弱い

今回は上2つの対応をしていきます。

1. 時間指定問題を解決する

Twitterで記事あげるときって20時くらいがちょうどいいという噂を聞いていたので、 そこを狙って作っていたにもかかわらず、なぜか13時ごろツイートが実行されてしまう問題

これを解決するのに、とりあえず時差を考慮して時間を設定し直しました。
過去のツイート時間を見ると17時間ほどずれている様子。
そしてどうせ直すなら19時〜23時くらいまで1時間おきにツイートできるようにしたい。

というわけで、こんな感じに変更。

@sched.scheduled_job('cron', hour=2)
@sched.scheduled_job('cron', hour=3)
@sched.scheduled_job('cron', hour=4)
@sched.scheduled_job('cron', hour=5)
@sched.scheduled_job('cron', hour=6)
def scheduled_job():
    autoTweet()

これで上手いこといくはず。 実はこの記事書いているときに、時間設定上手くいってなかったことが発覚したので、結果は今晩わかります。

2. 1時間おきに、違う記事をツイートする

上の方法で、1時間おきにcronを実行することができるので、
今度はそこでツイートする内容を詰めていきます。

理想は、毎回違うツイートがランダムに投稿されること。
そうすれば記事が増えても、リストに追加するだけで毎日5件ずつ記事をつぶやいてくれる。

やり方は非常に簡単で、
1. リストを用意する
2. 無限ループで乱数を回し、それを添え字にしてツイートする

このときに、同じツイート内容だとduplicateで弾かれるはずなので、
try文でくくることで、失敗したらもう一回乱数発生させて成功するまで繰り返すって感じにしています。
今のところうまいこと5個の記事が順番につぶやかれているので成功してるみたい。

import random
def autoTweet():
    tweets=[
        "PythonとSeleniumで自分のツイートを抽出する - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/01/173359",
        "JavaとSeleniumで自分のツイートを抽出する - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/01/201337",
        "NewsPicksでスクレイピングやってみた - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/05/28/235823",
        "Tweepyでpythonについて呟いたアカウントをフォローしまくってみた - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/08/151110",
        "フォローとツイートを定期実行してみた - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/31/220047"
        ]

    while True:
        index = random.randint(0,4)
        try:
            api.update_status(tweets[index]) 
            print('ツイートに成功しました')
            break
        except:
            continue

oauth認証などは過去記事を参照してください。

taikomegane.hatenablog.jp

結果はこんな感じ。

無事上手くいきました。 あとは検索条件ですね。ここはそんなに重要度高くないので後回しにしちゃうけど、そのうち対応します。

それでは。

フォローとツイートを定期実行してみた

久しぶりの投稿。 なんやかんやと毎週勉強してはいるのだけど、ブログにするのが面倒で放置してました。 今日同じ処理するのに迷ったので、備忘録的にあげます。

やりたいこと

  • ブログのURLをツイートしたい
  • 興味ありそうな人をフォローしたい
  • 全部自動で定期実行したい

ちなみに前回あげたこの記事の続きなので、oauth使うところは飛ばします。

taikomegane.hatenablog.jp

使ったもの

  • Tweepy
  • heroku

Tweepy Documentation — tweepy 3.5.0 documentation

devcenter.heroku.com

実際にやってみた

1. 自動ツイートしたい

今回は最終的にrun.pyを用意して、そこから呼び出したいので、全て関数で実装しています。

コードはこんな感じ。

def autoTweet():
    tweets=[ # リストにツイートしたい内容を入れる
        "PythonとSeleniumで自分のツイートを抽出する - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/01/173359",
        "JavaとSeleniumで自分のツイートを抽出する - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/01/201337",
        "NewsPicksでスクレイピングやってみた - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/05/28/235823",
        "Tweepyでpythonについて呟いたアカウントをフォローしまくってみた - 駆け出し眼鏡のプログラミング道場 http://taikomegane.hatenablog.jp/entry/2017/07/08/151110"
        ]

    for tweet in tweets: # リストの中身を1つずつ取り出してツイート
        api.update_status(tweet) # update_statusでツイートできる

まずtweetsをリストにしてひたすらつぶやきたい内容を追加します。 あとはforループで、api.update_statusでつぶやくだけ。 簡単ですね。

ただこれだと、一斉に4ツイート流れてしまうので、 適当に時間の感覚をあけてつぶやいてもいいかも。

引数を用意して、リストの添字で呼び出せばOKかな。今度作ります ひとまずこれで一つ目の要望はクリア

2.興味ありそうな人をフォローしたい

これはこのブログからのもらいものを修正したものです。

review-of-my-life.blogspot.jp

  def autoFollow (num, query, count): # 引数にクエリーの数、クエリー、検索数を入力

    if num == 1: # クエリー1つならqに代入
        q = query

    else: # クエリーが2つなら、ANDを挟んでqに代入
        keywords =[query[0], query[1]]
        q = ' AND '.join(keywords)

    # searchで検索をかける(q=クエリ、countは検索数、langで日本語のみに絞れる
    search_results = api.search(q=q, count=count, lang="ja")

    for result in search_results: # 検索結果を順に処理
        screen_name = result.user._json['screen_name'] # 取り出した結果からscreen_nameを取り出す

        # 検索結果に自分が含まれるとエラーになるので、try文でくくる
        try:
            # create_friendshipでフォローする
            api.create_friendship(screen_name)

        # エラーのときは飛ばす
        except:
            continue

複数語句での検索もできるようにしました。

またpythonとかtwitterとかで検索かけると、 日本語以外のツイートがかなり混ざってしまうので、lang=“ja"で日本語指定をしています。

もう一つ躓いたポイントとして、 create_friendshipで自分をフォローしようとするとエラーになって 処理が止まってしまうので、try文でくくる必要があります。

3. 自動実行したい

ここからが本番です。 今回はherokuを使って自動実行していきます。

まずAPSchedulerを使って自動実行の設定を行います。

Advanced Python Scheduler — APScheduler 3.3.1.post7 documentation

from apscheduler.schedulers.blocking import BlockingScheduler

sched = BlockingScheduler() #インスタンス化

# @以下で定期実行の設定ができる
# intervalなら20分おきに実行
@sched.scheduled_job('interval', minutes=20)
def timed_job():
    print('This job is run every twenty minutes.')

# cronは御存知の通り。これだと9時に実行
@sched.scheduled_job('cron', hour=9)
def scheduled_job():
    autoFollow(2,["スクレイピング","python"],20)

# 20時に勝手にツイート
@sched.scheduled_job('cron', hour=20)
def scheduled_job():
    autoTweet()
    print('ツイートに成功しました')

sched.start() # おまじない?

とまあこんな具合に、前に作った関数を呼び出して実行していきます。 @sched.scheduled_jobで引数にintervalとかcronつけるだけで自動で実行できるんだからすごい

これでファイルの準備はひとまずできたので、herokuの準備をしていきます。 herokuのユーザ登録とかその辺はとりあえず他の記事に譲って、 実行に必要なファイルを作成していきます。

作成するファイルは以下3つ。

  • Procfile
  • requirement.txt
  • runtime.txt

どれもパッと作れます

clock: python3 run.py

今回は定期実行をしたいので clock ウェブページあげたかったらwebだし、ぼっとならbot その辺りはググってください。

APScheduler==3.0.0
cryptography==1.7.1
idna==2.2
oauthlib==2.0.2
pyasn1==0.1.9
pycosat==0.6.1
pycparser==2.17
pyOpenSSL==16.2.0
requests==2.12.4
requests-oauthlib==0.8.0
six==1.10.0
tweepy==3.5.0
twitter==1.12.1

いらないのも入ってそうな感じ。 ここに入っているものを立ち上げ時に読み込んでくれます

大事なのは、APSchedulerとtweepyかな

python-3.6.1

pythonのバージョンを指定するだけ。簡単。

ここまでできたら、以下のコマンドを順に行っていきます。

初めてのときだけ

heroku login #ログインする
heroku git:clone -a アプリ名

以下は毎回共通。

git add . #全部突っ込んで
git commit -m "update" #コミットして
git push heroku master #heroku masterにプッシュ
heroku ps:scale clock=1 #最後にプロセスを起動?して終わり

ちなみに、heroku logsで実行ログを見れるので、そこで結果を確認できます。

ひとまずここまで。

今後の課題

  • よく考えたらherokuの時間指定アメリカだから意味わからない時間に実行しているのでは
  • 検索で引数2つしかとれないの弱い
  • 毎回まとめてツイートしちゃうのどうにかしたい

Tweepyでpythonについて呟いたアカウントをフォローしまくってみた

こんにちは。毎週のように友達と集まっては土日もプログラミングをしている太鼓眼鏡です 最近集まる人数が増えてきて楽しい限り。興味ある人連絡ください。

今回の目標

今回の目標は、以下2手順。

  • Tweepyというライブラリで、単語検索
  • 検索にひっかかった人頭10人を自動フォロー

検索ワード自体はなんでもいいのだけど、今回はひとまずpythonで検索かけます。

参考記事

qiita.com

www.statsbeginner.net

kivantium.hateblo.jp

qiita.com

Tweepy Documentation — tweepy 3.3.0 documentation

コードを書いてみる

今回作ったのは2ファイル。初めてimportをしてみました

1. apiを利用するための準備

import tweepy

# 各種キーをセット
CONSUMER_KEY = 'xxxxxxxxxxxx'
CONSUMER_SECRET = 'xxxxxxxxxxxxx'
ACCESS_TOKEN = 'xxxxxxxxxxxxx'
ACCESS_SECRET = 'xxxxxxxxxxxxxxxxxx'

auth = tweepy.OAuthHandler(CONSUMER_KEY, CONSUMER_SECRET)
auth.set_access_token(ACCESS_TOKEN, ACCESS_SECRET)

#APIインスタンスを作成
api = tweepy.API(auth)

まずtweepyをインポートします。 その後Consumer keyなどをセットして、APIインスタンスを作成。 これは決まり文句みたいなものなのでここまでで保存しておきます。

今までは毎回これを頭に書いていたんだけど、 これをモジュールとしてimportできるということで、今回はそちらもチャレンジ。

ファイル名を「oauth.py」で保存。

2. 自動フォローしまくる

import oauth
api = oauth.api

q = "python" //検索ワードをセット
count = 10 //検索数をセット

//検索実行
search_results = api.search(q=q, count=count)

//結果を順番にフォロー
for result in search_results:
    screen_id = result.user._json['screen_name']
    print(screen_id)
    api.create_friendship(screen_id)

「import oauth」で「oauth.py」をインポート。この後呼び出しやすいように、oauth.apiapiにしておきます

あとは割りと直感的に読みやすいと思うんですが、

  1. 検索ワードと数を指定
  2. api.searchで検索を実行
  3. 検索結果から順にscreen_nameを取得、一応ターミナルに出力してからフォロー

実行結果

f:id:cyclemem:20170708150548p:plain

わりと簡単に10人一気にフォローができるのいいですね。 しかもすぐ5人くらいからフォローバック来たから、検索ワードで狙い撃ちしたらいい感じ。

JavaとSeleniumで自分のツイートを抽出する

今日3本目の投稿。さすがにエンジンかけすぎて疲れてきた。

次は宣言通り、こちらの記事と同じことをJavaでやります。

taikomegane.hatenablog.jp

今回のコードはこちらから
getTweet_var.java · GitHub

目次

やりたいこと

  • https://twitter.com/にアクセス
  • inputタグにユーザー名とパスワードを記入、ログイン
  • 最初のページから、マイページへ移動
  • 何もせずに出ている20ツイートくらいをテキストで抽出
  • 抽出したツイートをターミナルで表示+csv出力

前回はdockerで準備が出来ているところからのスタートだったのが、今回はSeleniumをダウンロードするところから、、辛かった

まずは下準備

今回Javaでやるには、手元でSeleniumを動かせるようにセッティングする必要がありました。

しかもPhantomJSでやるのもありかもしれないけれど、やり方よくわからないということで、Chromeで実行することに。

さらにEclipseを使わないと使えないので、そこで動くようにしてあげないといけない。

ここだけで1時間以上格闘していました。。

参考記事はこちjavaworld.helpfulness.jp

やりたい人がいるとは思えないけど、ここから必要なものはダウンロードできます。 http://www.seleniumhq.org/download/

JavaSeleniumは「Selenium Client & WebDriver Language Bindings」から、ChromeのWebDriverは「Third Party Drivers, Bindings, and Plugins」からダウンロードできます。

ちょっと余談ですが、ここで僕はzipファイルが解凍できない謎現象に襲われたので、こちらを元に解決しました。 takasumi.hatenablog.com

基本は最初の参考記事の通りにしてもらえればいいと思います。

一応、最終的なファイル構造はこんな感じ。

f:id:cyclemem:20170701194748p:plain

最後にcsv出力がしたかったのでoutputフォルダを追加しています。

実際にやってみる

1. chromeのブラウザを取得

最初に、前回PhantomJSでやっていたことをChromeでやるので、ブラウザを生成します。

//正直ちょっとよくわからないけど、ドライバの場所を教えてあげてるぽい
System.setProperty("webdriver.chrome.driver", "./driver/chromedriver");

//Webドライバを生成
WebDriver driver = new ChromeDriver();

2. Twitterにアクセス

もうStringが懐かしすぎて、いかにPythonが楽ちんに書けるかを実感する時間。

やっていることは前回と変わらず、

  • TwitterのURLを指定
  • driver.getでURLにアクセス
//Twitterにアクセス
String url = "https://twitter.com";
driver.get(url);
Thread.sleep(millis); //ちょっと休憩、今回millis=5000

結果は、こんな感じ。chromeでやってると実際にブラウザが立ち上がるので楽しい。 f:id:cyclemem:20170701195414p:plain

ただなぜかこっちだと英語版のページに飛ぶ。

余談ですが、javaでの遅延方法はこちらを参照 azuma006.hatenablog.com

3. ログインする

この辺が下準備後一番の山場でした。今まで型指定なしで取得してたから、途方にくれてたよね。

ここまでくるともうドキュメントを読み漁りながら進めるしかなく泣きながら書きました。

Generated Documentation (Untitled)

www.seleniumqref.com

こちらもやっていることは変わらず、ユーザIDとパスワードのテキストボックスを取得し、指定していた文字列をsendKeysで入力

//ユーザIDとパスワードを入力
WebElement e = driver.findElement(By.id("signin-email"));
e.clear();
e.sendKeys(user); //ユーザIDを入力

e = driver.findElement(By.id("signin-password"));
e.clear();
e.sendKeys(pass); //パスワードを入力
Thread.sleep(millis); //ちょっと休憩

記入されるとこんな感じ。実際に記入されていくのを見れるので超楽しい。 f:id:cyclemem:20170701195956p:plain

記入が確認できたらログインする。

ここで明らかに見えているのに「ログインボタンが見つからない」というエラーが。

ソースを見てみると、見えなくなっているログインボタンが上の方にあるらしく、invisibleなものは押せないというエラーのよう。というわけで今回はX-pathで指定。

//ログインボタンをクリック
e = driver.findElement(By.xpath("//*[@id='front-container']/div[2]/div[2]/form/table/tbody/tr/td[2]/button"));
e.click();
Thread.sleep(millis); //ちょっと休憩

ログイン出来たことを確認。ここからは日本語 f:id:cyclemem:20170701200145p:plain

4. マイページに移動

ここまできちゃうともう簡単。pythonのときと同じ指定でいける。

//マイページに移動
e = driver.findElement(By.cssSelector(".DashboardProfileCard-bg"));
e.click();
Thread.sleep(millis); //ちょっと休憩

f:id:cyclemem:20170701200259p:plain

5. ツイートを抽出して、コンソールに出力

ここも基本は同じ。型指定がしっかりあるので、ツイート情報はListにいれる。あとでcsv出力するために、String型でツイートをいれるArrayListも一応用意しておく。

これも余談ですが、拡張for文も最初書き方忘れてて苦しみました。python自由度高すぎる、、

//ツイート情報を取得
List<WebElement> tweetsElements = driver.findElements(By.cssSelector(".tweet-text"));

//csv出力用のリストを生成
ArrayList<String> tweets = new ArrayList<String>();

//ツイート情報から、テキストだけ取り出してコンソール出力
for (WebElement t : tweetsElements){
    String tweet = t.getText();
    tweets.add(tweet); //リストにも追加しておく
    System.out.println(tweet);
}

この結果コンソールに出力されたのがこちf:id:cyclemem:20170701200620p:plain

いい加減見飽きてきた同じツイート群

6. csvに出力

最後にcsvファイルに出力します。ここはほとんどこの記事をぱくりました。

CSVファイルを書き出す - Javaちょこっとリファレンス

try {
            //出力先を作成する
            FileWriter fw = new FileWriter("./output/test.csv", false);
            PrintWriter pw = new PrintWriter(new BufferedWriter(fw));

            //csvの頭作成
            pw.print("tweet\n");

            //内容を指定する
            for(String tweet: tweets){
                pw.print(tweet);
                pw.println();
            }

            //ファイルに書き出す
            pw.close();

            //終了メッセージを画面に出力する
            System.out.println("出力が完了しました。");

        } catch (IOException ex) {
            ex.printStackTrace();
        }

急にtry catchでくくりだす感じにあふれ出ている。

基本さっき作ったArrayListを順番にcsvファイルに書き込むだけです。一応終わったら「出力が完了しました」と書くようになってます。

結果がこちf:id:cyclemem:20170701200828p:plain

あとはブラウザを閉じて終わり。

まとめ

こんな感じでJavaでもSeleniumを使ってスクレイピングが出来ました。

これはそのまま業務で使えるからイイネ。ガンガン使っていこう。

正直両方やってみて、初めて使う技術はPythonでいろいろ遊んでみて、Javaでしっかり仕組み理解しながら書くってのが結構効果的な気がした。findElementでとってきてるのがWebElementだってpythonのときは意識しなかったし。

ひとまずここまで。では。

PythonとSeleniumで自分のツイートを抽出する

本日2件目。PythonSeleniumを使って自分のツイートを抽出します。 API叩けばすぐ済むことを敢えてスクレイピングでやる。熱い。

やりたいこと

  • https://twitter.com/にアクセス
  • ログインボタンを押し、出てきたinputタグにユーザー名とパスワードを記入、ログイン
  • 最初のページから、マイページへ移動
  • 何もせずに出ている20ツイートくらいをテキストで抽出
  • 抽出したツイートをターミナルで表示+csv出力

Seleniumの準備などにはdockerを使っています。 その辺りの環境構築は今回は省略。

今回試した方法

  1. PhantomJSという仮想ブラウザを取得
  2. Twitterにアクセス
  3. Seleniumでログイン
  4. マイページに移動
  5. ツイートを取得してターミナルに出力
  6. csvにも出力

元ネタとして参考にしたのは、こちら。

実はNewsPicksで似たようなことをしていたんだけど、後々アウトなことを知ったのであげられず。 なので今回はTwitterで簡単なバージョンを作ってみました。

コードはこちgetTweet · GitHub

それでは順に見ていきます。

1. PhantomJSのブラウザを取得

# PhantomJSのドライバを得る
browser = webdriver.PhantomJS()
browser.implicitly_wait(3) #念のため3秒待機

スクレイピングをやるときはマナーとして定期的に休みをとる。とらないとサーバにめちゃくちゃ負担かかるらしいので。

2. Twitterにアクセス

browser.get()で指定のURLにアクセス。 browser.save_screenshot()でスクリーンショットをとる。 今回はブログ用に写真をとってます。

# Twitterにアクセス
url = "https://twitter.com/"
browser.get(url)
browser.save_screenshot("toppage.png") #証拠写真撮影

証拠写真こちf:id:cyclemem:20170701165822p:plain

3. ログインする

まずは右上にあるログインボタンをクリック Seleniumだと、find_element_by_css_selectorでCSSセレクタを指定した要素が取得できる そこをe.click()でクリックしているだけ。

#ログインボタンをクリック
e = browser.find_element_by_css_selector(".StreamsLogin")
e.click()
browser.implicitly_wait(10) #反映に時間がかかるので待つ
browser.save_screenshot("login.png") #証拠写真撮影

そうすると、さっきの画面がこうなる。 f:id:cyclemem:20170701170054p:plain

次に指定したユーザIDとパスワードを入力する。 ここでUSER、PASSとなってるのは、あとで全文載せるけど、最初のほうで指定している さっきと同じ要領で、ユーザIDの入力欄を取得し、念のためclearで初期化。send_keysで指定文字列を入力する。

# ユーザIDとパスワードを入力
e = browser.find_element_by_css_selector(".email-input")
e.clear()
e.send_keys(USER) #ここでユーザIDを入力

e = browser.find_element_by_css_selector("input[type=password]")
e.clear()
e.send_keys(PASS) #ここでパスワードを入力

browser.implicitly_wait(5) #念のため5分待って
browser.save_screenshot("login_with_info.png") #証拠写真撮影

結果がこちら、 f:id:cyclemem:20170701170424p:plain

最後に、ログインボタンを取得してクリックするとログイン完了。

#送信ボタンをクリック
e = browser.find_element_by_css_selector(".submit")
e.click()
browser.implicitly_wait(5) #念のため5分待って
browser.save_screenshot("success.png") #証拠写真撮影

やったぜ f:id:cyclemem:20170701170525p:plain

4. マイページに移動

これは簡単で、上のページのアカウント情報にあるヘッダー画像をクリックすればいい。

#マイページに移動
e = browser.find_element_by_css_selector(".DashboardProfileCard-bg")
e.click()

browser.implicitly_wait(3) #念のため3秒待って
browser.save_screenshot("mypage.png") #証拠写真撮影

結果はこちら。自分のページに移動しています。 f:id:cyclemem:20170701171004p:plain

5. ツイートを抽出して、ターミナルに出力

さっきと同様にツイートを取得。今回は複数あるので、find_elements_by_css_selectorを使う。 element→elementsにするだけで複数形になる親切設計。

またこのあとcsvに書き込むときにツイートがリストになってると便利なので、事前に用意しておく。

ここまで出来たらツイートを出力したいのだけど、抽出したtweetsにはいろんな情報が入っているので、textだけを出力する。

# ツイートを抽出
tweets = browser.find_elements_by_css_selector(".tweet-text")

#csvに読み込む用のリストを生成
tweet_list = []

# ツイートの出力
for tweet in tweets:
    t = tweet.text #ツイートのテキストを出力
    tweet_list.append(t) #リストに追加
    print(t) #ターミナルに出力

結果がこちら。黒い画面かっこいい! f:id:cyclemem:20170701171319p:plain

6. csvに出力

さっきのだけだと面白くないので、せっかくだから外部ファイルに出力する。

# csvに入れまくる
with codecs.open("tweets.csv", "w", "utf-8") as fp:
    writer = csv.writer(fp, delimiter=",", quotechar='"')
    writer.writerow(["tweet"])
    for tweet in tweet_list:
        writer.writerow([tweet])

結果は、こんな感じ。内容は変わらないけど。 f:id:cyclemem:20170701171437p:plain

以上!

まとめ

こんな感じでSeleniumを使ってログインからスクレイピングまでは上手くいきました。 ただ業務で使うのはJavaなので、この後そっちでも試してみます。 またあげるかも。では。

満腹Java①JFrameでいぬクイズ作ってみた

こんにちは。土日は昼間からプログラムが書けて最高ですね。 今日は友達ともくもくしながら、Javaを久しぶりに書いていました。

今回の教科書はこちら。

満腹Java―Javaアプリケーション開発編

満腹Java―Javaアプリケーション開発編

割りと古めなのだけど、せっかく家にあったのと、Swing?を勉強しろと上司に言われていたので見てみた次第です。

今回の成果物はこちら。 github.com

ざっくり何が出来るのかというと、Javaでフレームを作って、そこで動くアプリケーションが作れる」みたいです。

こないだまで色々やってたのはブラウザでやってたけど、ブラウザごと自作するみたいな感じかしら。 たまにあるフリーのJavaのソフトウェアとかが近いのかなと思います。

今回は、それを使っていぬの種類をあてるクイズを作りました。 かなりシンプルだけどシュールで面白い笑

いぬクイズ概要

  1. 起動するとフレームが生成される
  2. 上の方にクイズが出て、画像をクリックすると下に結果が出る

これだけです。全貌はこんな感じ。シュール。 f:id:cyclemem:20170701145558p:plain

見えないけど、上の方に小さく「ラブラドールレトリバーはどれだ」と書いてあります

実際にやってみる

さて、いぬ好きさんの皆さんなら全部わかりますよね。 左上から順に、

らしいです。 「いぬ フリー」で検索して出てきた画像を適当に4つ選んだだけなので他意はありません。

そこでまずは正解を選んでみます。 f:id:cyclemem:20170701145942p:plain

左下の方に小さく「あたり」って出てますね。

次、はずれを選びます。 f:id:cyclemem:20170701150045p:plain

今度は左下に、「はずれ、これはヨークシャーテリア」と出てますね。

これだけです。

コード紹介

これだけだとかなりシンプルですね。ちなみにさっきの本の2章目だけ読めばできます。

いぬクイズ

今日はまだ時間あるので、このくらいのレベル感のものを適当にあげていきます。 では。

入門ソーシャルデータ②TwitterAPIトレンド検索からツイート検索まで

こんばんは。今日は昨日の続きです。 taikomegane.hatenablog.jp

さて、まずは昨日非常に長ったらしい出力で終わってしまったtrend検索。 これを綺麗にしましょう。

トレンド検索をして、結果をjson形式で出力しよう

結論からいうと、json形式で出力しちゃえばOKということらしく、、

import twitter
import json #ここ

CONSUMER_KEY = ''
CONSUMER_SECRET = ''
OAUTH_TOKEN = ''
OAUTH_TOKEN_SECRET = ''

auth = twitter.oauth.OAuth(OAUTH_TOKEN, OAUTH_TOKEN_SECRET, CONSUMER_KEY, CONSUMER_SECRET)

twitter_api = twitter.Twitter(auth=auth)

WORLD_WOE_ID = 1
US_WOE_ID = 23424977

worId_trends = twitter_api.trends.place(_id=WORLD_WOE_ID)
us_trends = twitter_api.trends.place(_id=US_WOE_ID)

print(json.dumps(worId_trends, indent=1)) #ここ
print(json.dumps(us_trends, indent=1)) #ここ

コメントつけた3箇所を修正するだけで、こんな感じになる

[
 {
  "trends": [
   {
    "name": "#ThursdayThoughts",
    "url": "http://twitter.com/search?q=%23ThursdayThoughts",
    "promoted_content": null,
    "query": "%23ThursdayThoughts",
    "tweet_volume": 26178
   },
   {
    "name": "#iPhoneAt10",
    "url": "http://twitter.com/search?q=%23iPhoneAt10",
    "promoted_content": null,
    "query": "%23iPhoneAt10",
    "tweet_volume": null
   }

ちなみにちょくちょく出てくる%23は#のことらしい。

twitter.com

ここから先は、頭のoauthのところは全部同じなのでそこはコメントで端折ります。 次のステップは、、

世界とアメリカのトレンドから共通項目だけ抽出しよう

共通項目の抽出にはpythonのsetなるものを使うらしい。 参考資料はこち

uxmilk.jp

さて、やってみる。

import twitter

#この辺でconsumer_keyとかいろいろやってる

twitter_api = twitter.Twitter(auth=auth)

WORLD_WOE_ID = 1 #世界
US_WOE_ID = 23424977 #アメリカ

#世界のトレンドを入手
worId_trends = twitter_api.trends.place(_id=WORLD_WOE_ID)

#アメリカのトレンドを入手
us_trends = twitter_api.trends.place(_id=US_WOE_ID)

#トレンドのリストを拡張for文でset
world_trends_set = set([trend['name'] for trend in worId_trends[0]['trends']])
us_trends_set = set([trend['name'] for trend in us_trends[0]['trends']])

#&で積集合を算出、出力
common_trends = world_trends_set & us_trends_set
print(common_trends)

結果はこんな感じ

{"Trump's Obama Obsession", '#ThursdayThoughts', '#iPhoneAt10', '#FelizJueves', '#29Jun'}

はい、じゃあ今度はこの中の #iPhoneAt10を使ってツイートを検索します。

ハッシュタグでツイートを検索しよう

検索に使うのはGET search APIです。 GET search/tweets — Twitter Developers

import twitter
import json

#いつものやつ
twitter_api = twitter.Twitter(auth=auth)

#queryと検索数を指定
q = "#iPhoneAt10"
count = 100

#検索結果をsearch_resultsに保存
search_results = twitter_api.search.tweets(q=q, count=count)
statuses = search_results['statuses']

#ここから先がよくわからない
for _ in range(5):
    print ("Length of status", len(statuses))
    try:
        next_results = search_results['search_metadata']['next_results']
    except KeyError: #next_resultsがない場合は、もう結果がない
        break

    kwargs = dict([ kv.split('=') for kv in next_results[1:].split('&')])

    search_results = twitter_api.search.tweets(**kwargs)
    statuses += search_results['statuses']

#結果を出力!
print (json.dumps(statuses[0], indent=1))

とまあこんな感じである。 結果はなんかいろいろ出てしまうので書かないけど。

さてひとまずここまで。

次までの宿題と次にやること

  • pythonのfor文でrange()って何?調べておく
  • 検索結果のメタデータが意味不明すぎるのでドキュメントを読んでおく
  • pythonの辞書について完全に忘れているので復習する

ちなみに次にやることは、以下の通り。何それ超楽しそう。

  • ツイートエンティティを抽出する
  • 頻度分析を使ってツイートとツイートエンティティを分析する
  • ツイートの語彙的多様性を計算する

頑張っていきましょー。それでは。