Twitterと位置情報

位置情報使ってますか。
天気アプリやゲームアプリに利用される位置情報ですが、ツイートにも付与することができます。Twitter APIとpythonを使って位置情報付きツイートを調べる方法をまとめました。最後に可視化もしてみます。

位置情報のソース

Twitterで扱う位置情報にはツイートに付随する位置情報とユーザーのプロフィールに記述された位置情報があります。両方が存在する場合、検索では前者が優先されます(ソース)。

ユーザープロフィール

「東京」等の大雑把な記述でも位置情報として扱われます。

ツイート

画像付きツイートに位置情報が付与できます(ソース)。
具体的な手順としては、位置情報利用を許可しているアカウントがTwitter公式アプリ(web不可)からGPS情報をもつ写真をツイートに添付すると位置情報を示すラベルをつけるかどうか尋ねられます。ラベルは候補から選べます。候補は地区名(東京都なら区)の他、exif情報を一時的に参照して近隣のランドマークや店舗が表示されます。

位置情報の取得

以下、tweepyモジュールで説明していきます。

緯度経度を指定して周囲のツイートを検索

Standard search

位置情報を指定した検索は無料版から利用可能ですが、Standard searchとPremium searchで指定の仕方が異なることに注意が必要です。
無料版の場合は、検索する際にパラメーターgeocodeを追加します。例えばこんな感じ。

tweets = tweepy.Cursor(api.search, q="ランチ",
                        geocode="35.6467139,139.707889,1km").items()

キーワード(パラメーターq)はあってもなくてもいいです。

Premium search

sandbox、premium、それ以上の環境ではパラメーターgeocodeは存在しません。代わりに、クエリにオペレーターを追加します(書式ソース)。tweepyもpremiumに対応したものを使ってください。区切りがスペースだったり、緯度と経度の順番が逆だったり微妙に書式が違います。例えばこんな感じ。

tweets = tweepy.Cursor(api.search_30_day,
                       environment_name="environment30d",
                       query="ランチ point_radius:[139.707889 35.6467139 1km]").items()

sandboxやpremiumでは位置情報に関するオペレーターが他にもいろいろあります(参照)。
四角く指定したり、緯度経度のある位置情報付きツイートのみを拾うこともできます。

ユーザープロフィールにおける位置情報

"tweet"をツイート1件分の検索結果のオブジェクトとすると以下のように取得できます。
tweet.user.location

ツイートの詳細位置情報

"tweet"をツイート1件分の検索結果のオブジェクトとすると以下のように取得できます。
tweet.place

検索に使われた位置情報がここに入りますが、プロフィールに位置情報があっても十分小さいスケールでなければここは空リストになります。恐らくTwitter内のgeo_idが付与されているスケールと同等かそれより細かい必要があります(東京なら区まで)。
tweet.placeの中身は以下のような一連のデータ。

Place(_api=<tweepy.api.API object at 0x7f239461a208>, id='07d9ee988e882004', url='https://api.twitter.com/1.1/geo/id/07d9ee988e882004.json', place_type='poi', name='らーめんこじろう 526', full_name='らーめんこじろう 526', country_code='JP', country='Japan', contained_within=[], bounding_box=BoundingBox(_api=<tweepy.api.API object at 0x7f239461a208>, type='Polygon', coordinates=[[[139.70517960458437, 35.6534869608034], [139.70517960458437, 35.6534869608034], [139.70517960458437, 35.6534869608034], [139.70517960458437, 35.6534869608034]]]), attributes={})

いくつか説明します。

  • id:地区かランドマークのgeo_id
  • place_type:city(地区)かpoi(ランドマーク、point)
  • name:地区名かランドマーク名
  • bounding_box.coordinates:緯度経度。地区の場合は地区を内包する四角形の4つのポイントの緯度経度が提供される。ランドマークの場合は4つのポイントが全て同じ値になる。

可視化してみよう

恵比寿駅の周辺で「ランチ」を含む1週間分のツイートを検索して、google mapで可視化してみます。Standard searchでやりましょう。
Google colaboratory上で動かしています。

!pip install tweepy
import tweepy
import pandas as pd
import re
consumer_api_key = "XXX"
consumer_api_secret_key = "XXX"
access_token = "XXX"
access_token_secret = "XXX"
auth = tweepy.OAuthHandler(consumer_api_key, consumer_api_secret_key)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth_handler=auth, wait_on_rate_limit=True)
keyword = "ランチ"
geocode = "35.6467139,139.707889,1km"
tweets = tweepy.Cursor(api.search, q=keyword, tweet_mode="extended", geocode=geocode).items()
tweets_list  = [tweet._json for tweet in tweets]
df = pd.json_normalize(tweets_list)
df2 = df[df["place.place_type"]=="poi"] # ランドマークが指定されているもの
df2["place.bounding_box.coordinates.2"] = list(df2["place.bounding_box.coordinates"].map(lambda x: re.findall(pattern=r"\[\[\[(.+?)]", string=str(x))[0])) # 緯度経度の最初の1個を使用
df2 = df2[["place.bounding_box.coordinates.2", "place.full_name"]]
filename=keyword+"_"+geocode+"_1w"
df2.to_csv('/content/drive/My Drive/blog/{}_tweetdata.csv'.format(filename), index=False)

あとはgoogleマイマップにcsvデータを取り込みます。

できました!
Twitterにおいて位置情報が付与されているツイートは全体に対してごくわずかと言われていますが、案外取得できました。おいしいご飯の情報は人に共有したいですもんね。
今週のランチにお役立てください。


Header photo by Thor Alvis on Unsplash