Python独学ならTech-Joho TOP > いろいろやってみた > Pythonで、MySQL5.7のJSON型にツイートを保存してみる
取得したツイートを保存したい
前回、ツイッターから特定のキーワードで検索したツイートを取得するPythonプログラムをつくりました。
このままだと、検索したツイートは目でみて確認するだけで終わりで、あとで分析することもできません。ツイートを保存する仕組みが必要です。
MySQLのJSON型を使ってみたい
保存するにはデータベースを使います。しかし、データベースを言ってもいろいろな候補があります。
候補1: MongoDB
取得できるツイートはJSON形式で、リツイートの具合などによって構造は微妙に変わります。こういうときはNoSQLで、MongoDBが最初に思い浮かびました。
ただ、MongoDBは、あまりたくさんのデータを保存するのに向いていないところがあります。やたら容量をくって、えらい目にあった経験があり、余り使いたくありません。
他にもCouchDB、Cassandraなんかもちょっと考えましたが、よく知らないのと調べるのが面倒くさかったのでやめました。
候補2: MySQL
しっかりと、列の構造を決めて、ふつうにMySQLに保存するというのも考えました。しかし、モデルを作るのがめんどくさくてやめました。
JSON型
そこで思い出したのですが、MySQLの列のデータ型で、JSON型というのがあります。
単に一つの文字列型の列にJSON文字列を突っ込むように使えますが、検索などの際、JSONのキーで検索できるようです。
一度使ってみたかったのでこれにします。
MySQL5.6の後半から使えるようになったみたいです。
参考
https://www.webprofessional.jp/use-json-data-fields-mysql-databases/
https://www.s-style.co.jp/blog/2017/06/420/
CRATE文
こうなりました。
CREATE TABLE `tweets` ( `id` int(11) NOT NULL AUTO_INCREMENT, `content` json NOT NULL, `created` datetime DEFAULT CURRENT_TIMESTAMP, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
datetime型でも、DEFAULT CURRENT_TIMESTAMPで作成時間を入れられるようになったみたいです。
http://dekokun.github.io/posts/2014-05-31.html
MySQLは5.7.21にしました。
Pythonのコード
こうなりました。
from twython import TwythonStreamer, TwythonError
import json
import config
import mysql.connector
import sys
conn = mysql.connector.connect(
    host='localhost',
    port=3306,
    user=config.MYSQL_USER,
    password=config.MYSQL_PASS,
    database='twitter_app'
)
if not conn.is_connected():
    print('could not connect to db')
    sys.exit()
conn.ping(reconnect=True)
cur = conn.cursor()
class MyStreamer(TwythonStreamer):
    def on_success(self, data):
        json_text = json.dumps(data)
        try:
            sql = "insert into tweets (content) values (%s);"
            cur.execute(sql, (json_text,))
            conn.commit()
        except Exception as err:
            conn.rollback()
            print('could not commit inserting:', json_text)
            print('error:', err)
        if 'text' in data:
            print(data['text'])
    def on_error(self, status_code, data):
        print(status_code)
try:
    stream = MyStreamer(config.APP_KEY, config.APP_SECRET, config.ACCESS_TOKEN, config.ACCESS_TOKEN_SECRET)
    stream.statuses.filter(track='AKB')
except TwythonError as e:
    print(e)
configモジュールに、MySQLのパスワードなどいろいろな定数を入れています。
使っているライブラリはmysql-connector-python-rfになりました。mysql-pythonにしようとしたら、変なエラーがでてインストールできませんでした。
$ pip install mysql-connector-python-rf
ツイートの本文だけ取り出す
SELECT id, content->"$.text" AS `text` FROM sport_twitter_dev.tweets;
便利です。