【Python＋Bottle】Twitterの位置付きツイートを可視化するWebサービスをリリースしてみた

遡ること５月なんですが、Twitterの位置付きツイートを可視化するWebサービスをリリースしてみたお話。作りたいものができたら燃え尽きるこの性根をなんとかしたい。絶賛放置プレイ中であります。

bottleで作ってありますが、ものすごく簡素です。
なんせ重複はそのままだし、時刻も日本時間になってない。
細かいことはそのままで燃え尽きる好例ですこれは。





さて、APIに関しては当然　GET search/tweets　を使用。
geocodeオプションで近くのデータも任意で収集しようと。
全国で検索をかけるとサーチでは上位100件のキーワード検索になるので検索結果に位置付きツイートが出てこないことが。そうなると何も表示されないエラーページ出すしか無いって言うやつです。

他に良いやり方があるんでしょうけどそこまで思いつきませんでした。

ブラウザから位置情報を引っ張って処理。
その後近隣を探す場合の選択肢がある場合はその距離を

geocoding = send_geo + "," + near

で結合して渡す。

```
@route("/show", method="GET")
def send_geos():
	send_geo = request.query.send_geo
	search_words = request.query.search_words
	near = request.query.near
	geocoding = send_geo + "," + near
	
	
	if search_words:
		C_KEY = "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊"
		C_SECRET = "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊"
		A_KEY = "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊"
		A_SECRET = "＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊＊"

		url = "https://api.twitter.com/1.1/search/tweets.json?"
		
		if near:
			params = {
			"q": (search_words, "utf-8"),
			"lang": "ja",
			"geocode": (geocoding),
			"result_type": "mixed",
			"count": "100"
			}		
			tw = OAuth1Session(C_KEY,C_SECRET,A_KEY,A_SECRET)
			req = tw.get(url, params = params)
			tweets = json.loads(req.text)
			dic = tweets
		else:
			params = {
			"q": (search_words, "utf-8"),
			"lang": "ja",
			"result_type": "mixed",
			"count": "100"
			}		
			tw = OAuth1Session(C_KEY,C_SECRET,A_KEY,A_SECRET)
			req = tw.get(url, params = params)
			tweets = json.loads(req.text)
			dic = tweets

```



位置付きツイートが無い場合に問題が発生するので、そこをtryで逃げの対処。
位置付きではない場合はexceptで別の処理をさせる。

```

		if req.status_code == 200:
			for tweet in tweets["statuses"]:
				created_at = YmdHMS(tweet["created_at"])
				User = (tweet["user"]["screen_name"].encode("utf-8"))
				U_Name = (tweet["user"]["name"].encode("utf-8"))
				U_img = (tweet["user"]["profile_image_url"])
				Text = (tweet["text"].encode("utf-8"))
				if "http" in "Text":
					Text = Text.split("http", 1)[0]
					Text = Text.split("@")[0]
					Text = Text.split("RT")[0]


				try:
					Place = (tweet["place"]["bounding_box"]["coordinates"])
					
					flat_list = []
					for e in Place:
						flat_list.extend(e)
    	
					flat_list2 = []
					for b in flat_list:
						flat_list2.extend(b)
 
					flat_list3 = []
					for c in flat_list:
						flat_list3.extend(c)
    	
					geolng = flat_list3[0]
					geolat = flat_list3[1]
```

ジオコードは　(tweet["place"]["bounding_box"]["coordinates"])
で取りに行くわけですがこれでやるとネストがひどいのでネストを解除してます。

基本Pythonのスクリプト内処理はこれくらい。あとはtplファイルに直書きしてます。


以下のようにtplの中でPythonを書くという処理。
これでツイートが取得分ちゃんと全件表示される。


ツイートデータはデータベースに格納したものを引っ張るとか。
もうデータをプレーンテキストで保存しちゃうとか。

```
%for line in f:			
%	line = line.rstrip()
%	l = line.split(",")
%	User = l[0]
%	U_Name = l[1]
%	U_img = l[2]
%	Text = l[3]
%	created_at = l[-3]
%geolng = l[-1]
%geolat = l[-2]
<li class="twlist">
	<font size="2" color="#d8d8d8">{{created_at}}・{{geolat}},{{geolng}}</font><br>
	<span class="fleft"><a href="https://twitter.com/{{User}}" target="_blank"><img src="{{U_img}}"></a></span>
	<b>{{U_Name}}</b> <font size="2"><a href="https://twitter.com/{{User}}" target="_blank">@{{User}}</a></font><br>{{Text}}<br><hr class="clear">
</li>
%end
<ul>
```

tplに書くときはインデント無視でも処理できちゃう。
このまま書き出すと順序がおかしくなるのでJqueryで整形しちゃう。

```
<script type="text/javascript">
$(function () {
  $('ul').html(
    $('li').sort(function(a, b) {
      if ($(a).text() < $(b).text()) {
        return 1;
      } else {
        return -1;
      }
    })
  );
});
</script>
```

地図へのプロットも同様でGooglemap用のJavascriptの中にPython書いちゃう。

```
%for line in f:			
%	line = line.rstrip()
%	l = line.split(",")
%	User = l[0]
%	U_Name = l[1]
%	U_img = l[2]
%	Text = l[3]
%	created_at = l[-3]
%geolng = l[-1]
%geolat = l[-2]
              ['<a href=https://twitter.com/{{User}} target="_blank"><img src={{U_img}}></a><br>{{U_Name}}:{{User}}<br>{{created_at}}<br><marquee>{{Text}}</marquee>', {{geolat}}, {{geolng}}],
              
%end 
              ['You', {{default_tag}}]
```


{{User}}　なんかはbottleで　return template した変数。
Pythonスクリプト単体だと200行くらいの処理。


で、Web上で動かしてみるとこんな感じになりましたとさ。

http://www.geo-twit.com/


使い道？あるかなぁ・・・。