Twitterのタグ「#熊本大分のうまいもん教えて」でトピック分析してみた
20個のトピックの一覧
(0, '0.020*時 + 0.015*瑠異 + 0.015*沙 + 0.014*ざびえる + 0.013*ラーメン + 0.013*酢 + 0.013*カボスポン + 0.012*臼杵 + 0.012*あと + 0.011*名物') (1, '0.030*県 + 0.025*シュークリーム + 0.025*今 + 0.024*市 + 0.018*間違い + 0.016*普通 + 0.016*町 + 0.015*最高 + 0.015*氷川 + 0.014*天草') (2, '0.035*別府 + 0.017*近く + 0.016*県 + 0.016*定食 + 0.015*駅 + 0.013*テッパン + 0.012*地獄 + 0.012*最高 + 0.010*米 + 0.009*」') (3, '0.189*の + 0.188*皆 + 0.033*和菓子 + 0.031*紹介 + 0.017*県 + 0.016*私 + 0.016*褌 + 0.016*他人 + 0.016*笑 + 0.016*別') (4, '0.029*いま + 0.026*関 + 0.026*ネット + 0.026*人気 + 0.026*こちら + 0.024*馬刺し + 0.021*天 + 0.018*魚 + 0.017*美味 + 0.016*納豆') (5, '0.027*感じ + 0.019*堂 + 0.019*もち + 0.018*ざびえる + 0.017*菓子 + 0.016*白身 + 0.016*ピータン + 0.016*フラン + 0.016*シスコ + 0.016*ドン') (6, '0.112*地獄 + 0.076*プリン + 0.047*別府 + 0.044*食材 + 0.026*鉄輪 + 0.023*蒸し + 0.023*好き + 0.023*持ち込み + 0.022*工房 + 0.022*近く') (7, '0.057*天 + 0.033*中津 + 0.023*揚げ + 0.018*唐 + 0.017*やつ + 0.016*県 + 0.016*定食 + 0.015*湯布院 + 0.012*鶏 + 0.011*市') (8, '0.052*阿蘇 + 0.032*鶏 + 0.027*牛 + 0.027*南 + 0.026*あか + 0.026*茶 + 0.026*なん + 0.024*地 + 0.024*場所 + 0.024*円') (9, '0.094*よう + 0.094*方 + 0.092*ハッシュ + 0.092*応援 + 0.092*いろいろ + 0.092*気持ち + 0.012*きゅう + 0.012*りゅう + 0.010*木 + 0.006*いま') (10, '0.024*関 + 0.023*お菓子 + 0.022*一 + 0.022*中 + 0.022*餡 + 0.022*駅 + 0.022*かなり + 0.021*俺 + 0.021*キオスク + 0.021*紫色') (11, '0.019*みたい + 0.017*団子 + 0.016*天 + 0.014*芋 + 0.014*輪切り + 0.014*味 + 0.013*方 + 0.013*餡 + 0.012*やつ + 0.012*コーラ') (12, '0.044*す + 0.027*ラーメン + 0.025*すか + 0.022*全国 + 0.022*県民 + 0.022*消費 + 0.022*お願い + 0.022*数 + 0.022*大切 + 0.022*生産') (13, '0.067*菓子 + 0.042*復刻 + 0.025*代 + 0.025*二 + 0.025*以前 + 0.025*家 + 0.024*取材 + 0.024*編 + 0.024*現在 + 0.024*カリン') (14, '0.106*市 + 0.039*別府 + 0.032*竹田 + 0.028*豊後 + 0.028*由布 + 0.028*日田 + 0.028*被害 + 0.027*牛 + 0.021*天 + 0.020*三笠') (15, '0.039*別府 + 0.026*最高 + 0.025*月 + 0.025*城下 + 0.024*鰈 + 0.022*河豚 + 0.022*湖 + 0.022*餃子 + 0.014*しいたけ + 0.014*醤油') (16, '0.031*あと + 0.023*ー + 0.015*天 + 0.014*柚子 + 0.012*団子 + 0.011*但馬 + 0.011*老舗 + 0.010*感 + 0.009*天草 + 0.009*九州') (17, '0.020*スイカ + 0.019*飯 + 0.019*太平 + 0.018*団子 + 0.018*♡ + 0.018*鶏肉 + 0.017*ラーメン + 0.017*今回 + 0.017*テロ + 0.015*編') (18, '0.033*馬刺し + 0.032*プリン + 0.021*温泉 + 0.021*汁 + 0.019*飯 + 0.019*食 + 0.017*元気 + 0.017*トゥギャトピ + 0.017*情報 + 0.017*バッテラ') (19, '0.052*地獄 + 0.051*プリン + 0.035*辛子 + 0.028*ザビエル + 0.028*蓮根 + 0.016*あたり + 0.015*出荷 + 0.015*すいか + 0.015*天 + 0.015*汁')
20個のトピックそれぞれに最も関連するツイート
0: https://twitter.com/madda_be/status/723122647635107841 臼杵煎餅 生姜砂糖が塗された煎餅で独特の甘みと生姜の風味が良い煎餅。製造元も沢山あり好みを探そう!俺は後藤一筋。 なお、最近は最中のようにアイスを煎餅で挟んだものも出てる模様 #臼杵 #名物 #熊本大分のうまいもん教えて https://t.co/K60zfx5YUB 1: https://twitter.com/madda_be/status/723686938746589184 東京吉祥寺、東急百貨店。諸国名店とうまいもの大会。熊本県天草の天草生うに本舗 丸健水産で、桜うに満開丼&海鮮ひたまぶし。天草のウニうめーぞヽ(´▽`)ノ #熊本大分のうまいもん教えて https://t.co/u1e4ssk8vQ 2: https://twitter.com/madda_be/status/723128702163251200 #熊本大分のうまいもん教えて 大分県国東市の道の駅くにさき、その中にある「銀たちの郷」で食べることができる太刀重はすごくお勧め。 太刀魚の蒲焼とタレの味わいが絶妙です。ぜひ一度お試しあれ。 https://t.co/T3HIqKrra2 3: https://twitter.com/madda_be/status/723132760609558528 お酒が飲みたい方には中津郵便局の横にあるセントフェローズ。おいしいカクテルが楽しめます。なんといっても雰囲気が良い。カウンターで飲むとマッキントッシュの真空管アンプを酒の肴に呑めるというオーディオ好きにも優しいお店です。 #熊本大分のうまいもん教えて 4: https://twitter.com/madda_be/status/723117101557288960 大分はだご汁、鳥天、唐揚げは基本。普通に買えるお土産なら、ザビエル、豊後手焼きせんべいはオススメ。 大分は海の幸、山の幸が豊富で美味な物だらけ。 余り知られてない?けど、豊後牛(黒毛和牛)も美味しいよ😊関アジ、関サバじゃなくても魚も美味です🐟 #熊本大分のうまいもん教えて 5: https://twitter.com/madda_be/status/723137807250661376 温泉ピータンとかいう不思議なものもありました大分。白身がもちもちしていてかなりの謎食感。ゆで卵の白身とわらび餅のあいの子みたいな。ピータンかと言われると微妙ですが、こんな食べ物もあるんだ的な感じで。 https://t.co/ZUDZs3sfm7 #熊本大分のうまいもん教えて 6: https://twitter.com/madda_be/status/723134013066477569 まだオープンしたばかりですが、七城町蘇崎の地元熊本の赤身肉を無添加で加工調理したオーガニックカフェ「ママトコ」、ヘルシーでボリュームあっておすすめです。ウインナー作り体験やBBQもできます!また行きたい #熊本大分のうまいもん教えて https://t.co/PJvdVYSQyj 7: https://twitter.com/madda_be/status/723128697230790661 大分県中津市のお食事処、鬼太郎。オススメは鬼から定食。中津と宇佐を中心にB級グルメとして有名なから揚げを豪快に楽しめます。鬼めしという炊き込み御飯も絶品。他にも鱧が楽しめます。中津駅を降りて徒歩5分! #熊本大分のうまいもん教えて https://t.co/ZOAoVj2V3O 8: https://twitter.com/madda_be/status/723140647092252672 熊本は紅蘭亭の太平燕!鶏ガラと豚骨の合わせスープにたっぷり野菜や海鮮などの具材の旨味が春雨のつるつるした食感とよく合って、一口ごとに幸せな心持ちになれます。素揚げされたゆで卵の食感も楽しい。 https://t.co/xz3bRMzDmW #熊本大分のうまいもん教えて 9: https://twitter.com/madda_be/status/722970612201717760 父の畑でとれた晩白柚。祖母が生前適当に植えてて柑橘類+αの木が7、8種ほどあり草刈り剪定する他は自由にのびのび育ってます。左は長女が友人から余ってるからあげると貰ってきたデコポンオレ。美味しかったです #熊本大分のうまいもん教えて https://t.co/PsxGCoUSop 10: https://twitter.com/madda_be/status/723135447614935040 お酒が好きな方には耶馬美人なんか如何でしょう。辛口の焼酎で、焼酎と言うよりは日本酒に近い味わいです。あと、長洲には兼八というお酒(これも焼酎)の醸造元があります。あの辺は古い町並みも楽しめるので腹ごなしに散歩してはいかがでしょう。 #熊本大分のうまいもん教えて 11: https://twitter.com/madda_be/status/723567399874633728 山内本店の匠ラスク ママちゃんが頂いてきた物 知り合いの方が九州の物産フェアで 購入した物なんだって 熊本だ!ってたくさん買ったみたい 食べたことないラスク! みたらしみたいな味でおいしい~💕 #熊本大分のうまいもん教えて https://t.co/ued5Dex88h 12: https://twitter.com/madda_be/status/723430824402546688 熊本限定になりますが、馬刺し、辛子蓮根、タイピーエン、ラーメン、ダゴ汁あたりが定番。カレー屋さんもお蕎麦屋さんも美味しいお店多いですよ。裏メニュー的な奴では、ちょぼ焼。B級グルメ的にイチオシです(・∀・) #熊本大分のうまいもん教えて 13: https://twitter.com/madda_be/status/723134113901776896 ざびえる本舗の工場と大分駅裏の南蛮珈琲館では焼きたての『ざびえる』を提供。さっくりした外皮にしっとりした甘味が美味。しかし、「焼きたてのざびえる」って聞く度に火炙りになったザビエルを想像してしまうな #熊本大分のうまいもん教えて https://t.co/rIR8ylH3Ed 14: https://twitter.com/madda_be/status/723124647798018053 大分は別府市、由布市、日田市、玖珠郡、竹田市あたりが被害がひどいようなので…。別府市と由布市には地震が収まったら来てください。被害地域では豊後牛の肥育が盛んです。竹田市は銘菓「荒城の月」「三笠野」があります。日田は醤油、たらおさ、焼きそば。 #熊本大分のうまいもん教えて #大分 15: https://twitter.com/madda_be/status/723445110520713217 阿蘇あか牛、すいか、いちご、メロン、キャベツ、とうきび、馬刺し、陣太鼓、武者返し、銀杏パイ、山鹿灯籠最中、甘夏、とり宮のコロッケ、高森銘水、人吉の駅弁、いまきん食堂、白川水源の水まんじゅう、天草の海鮮、あそぼーい!のロコモコ弁当とプリン #熊本大分のうまいもん教えて 16: https://twitter.com/madda_be/status/723123659603214338 植木のスイカは確かに九州産としては最高峰だと思います。あと、熊本ラーメンです。地震が落ち着いたら、ラーメンば食べに来んね。あとは、県外の人にやさしい!。あと、塩トマトが最近は有名になったかな。いきなり万十は、熊本に来て食べて下さい! #熊本大分のうまいもん教えて #熊本 17: https://twitter.com/madda_be/status/723119414258737152 #熊本大分のうまいもん教えて 熊本はスイカの名産地とのことで、過去の作品からこちらを。#watercolor #illustration (ハッシュタグを多くの方にご覧いただき、RTや♡をありがとうございます。飯テロすごいです) https://t.co/6qpJHMIJkb 18: https://twitter.com/madda_be/status/723468990425616384 球磨焼酎 球磨川の鮎 かぼす味噌(脂肪の吸着を防ぐ!) 柚子胡椒(イチオシは下村婦人会のもの) #熊本大分のうまいもん教えて 19: https://twitter.com/madda_be/status/723128074749931520 #熊本大分のうまいもん教えて やっぱり飲兵衛としては赤酒のお屠蘇ですかねー。これがないとお正月は!お節とか数の子とかと最高ーーーーに合う♡♡♡
参考にしたサイト
- Python で Twitter API にアクセス - Qiita
- Python3 で MeCab を使う - Dimension Planet Adventure 最終章 最終話『栄光なる未来』
- Python で Mecabを利用する【mac】 - 39Si
- Python用のトピックモデルのライブラリgensim の使い方(主に日本語のテキストの読み込み) - 唯物是真 @Scaled_Wurm
- MeCabをPython3から使う(続報) - Shogo's Blog
手順
1.Twitterから検索結果を取得する
参考:Python で Twitter API にアクセス - Qiita
from requests_oauthlib import OAuth1Session import json CK = 'XXXXXXXXXXXXXXXXXXXXXX' # Consumer Key CS = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' # Consumer Secret AT = 'XXXXXXXXX-XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' # Access Token AS = 'XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX' # Accesss Token Secert # 検索API url = "https://api.twitter.com/1.1/search/tweets.json" params = {"q":"#熊本大分のうまいもん教えて",'count':100} # OAuth認証で POST method で投稿 twitter = OAuth1Session(CK, CS, AT, AS) req = twitter.post(url, params = params) # レスポンスを確認 if req.status_code == 200: timeline = json.loads(req.text) # 各ツイートの本文を表示 for tweet in timeline[u'statuses']: print(tweet["text"]) else: print ("Error: %d" % req.status_code)
2.取得したデータを保存する
#初回の保存 import pickle with open('tweets.dump', 'wb') as f: data=[] data.append(timeline) pickle.dump(data,f)
3.さらにTwitterから3000件分の検索結果をまとめて取得してファイルに保存する
import time for i in range(0,30): print(i) #次の検索がなくなった場合と、検索結果がない場合は終了 if not u'next_results' in timeline[u'search_metadata']: break if len(timeline[u'statuses'])==0: break #次のIDを取得 max_id = timeline[u'search_metadata'][u'next_results'].split("&")[0].split("=")[1] print(max_id) #以前のデータを読み込み print("loading") prevdata = [] with open('tweets.dump', 'rb') as f: prevdata = pickle.load(f) print("loaded") #リクエストを投げて params = {"q":"#熊本大分のうまいもん教えて",'count':100,"max_id":max_id} # OAuth で GET req = twitter.get(url, params = params) if req.status_code == 200: # レスポンスはJSON形式なので parse する timeline = json.loads(req.text) # 各ツイートの本文を表示 #for tweet in timeline[u'statuses']: # print(tweet["text"]) #データを延長して更新 data=prevdata print("saving") with open('tweets.dump', 'wb') as f: data.append(timeline) pickle.dump(data,f) print("saved") else: # エラーの場合 print ("Error: %d" % req.status_code) time.sleep(60*16)#16分待つ print("end")
4.分析用にデータを読み込む
import pickle with open('tweets.dump', 'rb') as f: data_for_test = pickle.load(f) print("loaded") print(len(data_for_test))
5.MeCabと正規表現でテキストを加工して、gensim用にファイルを作成する
import gensim import MeCab import re i=0 for tweets in data_for_test: for tweet in tweets["statuses"]: i=i+1 with open('data.text', 'w') as f: f.write(str(i)+"\n") for tweets in data_for_test: for tweet in tweets["statuses"]: sample=tweet["text"] sample=re.sub(r'https?://[\w/:%#\$&\?\(\)~\.=\+\-…]+', "", sample) sample=re.sub('RT', "", sample) sample=re.sub('#熊本大分のうまいもん教えて', "", sample) sample=re.sub('さん', "", sample) sample=re.sub('もの', "", sample) sample=re.sub('これ', "", sample) sample=re.sub('こと', "", sample) sample=re.sub('タグ', "", sample) sample=re.sub('熊本', "", sample) sample=re.sub('大分', "", sample) sample=re.sub('店', "", sample) sample=re.sub('屋', "", sample) sample=re.sub('お気に入り', "", sample) sample=re.sub('まとめ', "", sample) sample=re.sub(r'[!-~]', "", sample)#半角記号,数字,英字 sample=re.sub(r'[︰-@]', "", sample)#全角記号 mecab = MeCab.Tagger("-Owakati") mecab.parse('') #res = mecab.parse(sample) res="" node = mecab.parseToNode(sample) while node: if node.feature.split(",")[0]=="名詞": res += node.surface+" " #print(node.surface) node = node.next res=res.rstrip()+"\n" res=re.sub(' ん', "", res) res=re.sub(' の', "", res) #print(res) #print(sample) #print(type(res)) #if in prevdocs={:} with open('data.text', 'a') as f: f.write(res) with open('data.text', 'r') as f: print(f.read())
6.gensimのLDAでトピック分析する
参考:Python用のトピックモデルのライブラリgensim の使い方(主に日本語のテキストの読み込み) - 唯物是真 @Scaled_Wurm
corpus = gensim.corpora.lowcorpus.LowCorpus('data.text') print(corpus) lda = gensim.models.ldamodel.LdaModel(corpus=corpus, num_topics=20, id2word=corpus.id2word) print(lda) topiclist=[]
トピックの一覧を出力
for topic in lda.show_topics(-1): print(topic) topiclist.append(topic[1])
トピックに最も関連しているTweetの一覧を出力
#各文書が属するトピックをまとめる repdoclist=[0 for i in range(0,20)] stlist=[0 for i in range(0,20)] print(len(repdoclist)) i=0 for topics_per_document in lda[corpus]: for t in topics_per_document: num=t[0] st =t[1] if stlist[num]<st: stlist[num]=st repdoclist[num]=i print(topics_per_document) i+=1 #表示用にツイートのデータを整形して保存しておく doclist=[] for tweets in data_for_test: for tweet in tweets["statuses"]: if "retweeted_status" in tweet and "text" in tweet["retweeted_status"]: sample=tweet["retweeted_status"]["text"] else: sample=tweet["text"] doclist.append(sample) idlist=[] for tweets in data_for_test: for tweet in tweets["statuses"]: if "retweeted_status" in tweet and "text" in tweet["retweeted_status"]: sample=tweet["retweeted_status"]["id_str"] else: sample=tweet["id_str"] idlist.append(sample) #各トピックに最も関連するツイートを出力 count = 0 for i in repdoclist: print("\n",str(count)+":","https://twitter.com/madda_be/status/"+idlist[i],"\n",doclist[i]) count+=1
Java8のラムダ式サンプル
https://github.com/taguro/SampleCode/blob/master/JavaLambdaSample.java
import java.util.ArrayList; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Predicate; public class MainThread { public static void main(String[] args) { innerInterface test = ()->{System.out.println("hello");}; test.express(); //ラムダ式は、{}の外側で宣言している定数を参照できる String hoge ="{}の外側の定数"; test = ()->{System.out.println(hoge);}; test.express(); //処理が1行の時は{}を省略できる String foo ="{}は省略OK"; test = ()->System.out.println(foo); test.express(); //もちろん引数を与えることもできる innerInterface2 test2 = (hoge2)->{System.out.println(hoge2);}; test2.express("これは引数"); //定義しないでも、引数を1つ受け取って、処理を行うためのインターフェースは用意されてる Consumertest3 = (hoge2)->{System.out.println(hoge2);}; test3.accept("返り値のない処理にはConsumer を使おう"); //引数を1つ受け取って値を返すためのインターフェース Function hogeCheck = (x)-> x == "hoge"; if(hogeCheck.apply("hoge"))System.out.println("返り値のある処理にはFunction を使おう"); //引数を1つ受け取ってbooleanを返すインターフェースも既にある。他にも基本的なものは既にある。らしい。 Predicate hogeCheck2 = (x)-> x == "hoge"; if(hogeCheck2.test("hoge")){System.out.println("booleanを返す処理にはPredicate を使おう");} //上の例だとラムダ式(と無名クラス)のありがたさが分からないので、別のクラスに処理を埋め込む例 String localVariable="この"; innerClass3.showAfterCheck("別のクラスの処理に、このメソッドのローカル変数を組み込めた!", (x)->{return x.contains(localVariable);}); //もちろん無名クラスを使って、こうすることもできる Predicate pred= new Predicate (){ @Override public boolean test(String t) { return t.contains(localVariable); } }; innerClass3.showAfterCheck("無名クラスを使ったこの方法もOK", pred); //無名クラスを使った方法を略記すると innerClass3.showAfterCheck("やっぱり無名クラスを使ったこの方法は少し書く文字が多い。new Predicate ってわざわざ書きたくない", new Predicate (){ @Override public boolean test(String t) { return t.contains(localVariable); } }); //実用上はこんな使い方。短いので少し嬉しい。 String str = "Threadでラムダ式"; Thread thread = new Thread(()->{System.out.println(str);}); thread.start(); //おまけ:引数2つ以上使いたいときどうするか? //こうするとFunction hoge = (x,y)->{return x.equals(y);};エラーになる //C#だと引数2つ以上の時も、既に定義されている型Action(返り値なしの処理の場合)とFunc(返り値のある処理の場合)で //こんな風にFunc<引数1の型,引数2の型,返り値の型> hoge = (x,y)=>{return x.equals(y);} 宣言できるけれど、javaではダメらしい。 //どうするかというと、innerInterface4みたいなの用意したり、List使うとかか。あるいは引数で渡すのは諦めてローカル変数を使う構成にするとか。 innerInterface4 inner4 = (x,y,z)->{System.out.println(x+y+z);return x+y+z;}; inner4.express("引数を複数与えるために、@FunctionalInterface", "を", "使う方法"); ArrayList array = new ArrayList(); array.add(3); array.add("3"); Predicate test5 = (x)->{ Object obj1 = x.get(0).toString(); Object obj2 = (String)x.get(1); return obj1.equals(obj2);}; if(test5.test(array)){System.out.println("ArrayListを使った方法も一応動く");} } //@FunctionalInterfaceというアノテーションを付けることで、ラムダ式のインターフェースを新たに定義できる @FunctionalInterface private interface innerInterface{ public void express(); } @FunctionalInterface private interface innerInterface2{ public void express(String str); } @FunctionalInterface private interface innerInterface3{ public void express(String str); } public static class innerClass3{ public static void showAfterCheck(String str,Predicate pred){ if(pred.test(str))System.out.println(str); } } @FunctionalInterface private interface innerInterface4{ public String express(String str,String str2, String str3); } }