見出し画像

MySQL×Django×Tweepy_文字コードを変更して絵文字を保存できるようにする #123日目

tweepyでツイート情報を収集してMySQLに保存していたのですが、絵文字を保存しようするとエラーになったため、これを除外するようなコードを書いて保存していました。

ただ、MySQLの文字コードを「utf8mb4」に変更すれば絵文字を保存できるようになると知ったのでそれを試してみました。


環境

windows10
MySQL (MAMP)  Ver 14.14 Distrib 5.6.34,
Django 3, 2, 8


MySQLの文字コードを変更する

まずは普通にMySQLのテーブル情報を一覧して文字コードを確認します。

SHOW CREATE TABLE tweepy_test_tweets;

↓出力結果

| tweepy_test_tweets | CREATE TABLE `tweepy_test_tweets` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `tweet_id` varchar(255) NOT NULL,
  `user_id` varchar(255) NOT NULL,
  `user_name` varchar(225) NOT NULL,
  `text` longtext,
  `favorite` int(10) unsigned NOT NULL,
  `retweet` int(10) unsigned NOT NULL,
  `created_at` datetime(6) NOT NULL,
  `loaded_at` datetime(6) NOT NULL,
  `keyword` varchar(255) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `tweet_unique` (`keyword`,`tweet_id`)
) ENGINE=InnoDB AUTO_INCREMENT=344 DEFAULT CHARSET=utf8 |


次に、テーブルの文字コードを変更するコードを実行してみます。
(tweepy_test_tweetsがテーブル名です)

ALTER TABLE tweepy_test_tweets CONVERT TO CHARACTER SET utf8mb4;

↓ただしこのままではエラーが出てしまいます。

ERROR 1071 (42000): Specified key was too long; max key length is 767 bytes


これは「key長の制限は最大767バイトだけどそれを超えているよ」というエラーです。utf8だと制限内に収まっていたものが、utf8mb4だと超えてしまっています。

utf8のときは、設定してた文字数から最大のバイト数は以下になっていました。制限である767バイトにギリギリ収まっています。

varchar(255) × 3バイト(utf8) = 765バイト

これをutfmb4にすると、以下のように制限を超えてしまいます。

varchar(255) × 4バイト(utf8mb4) = 1,020バイト


そのため、文字数を減らして767バイトに収まるようにする必要があります。今回はDjangoを使っているので、models.pyから文字数を変更してマイグレーションします。

190文字に設定変更しました(190 × 4 = 760バイト)

[models.py]
 
class Tweets(models.Model):
    keyword = models.CharField(
        "検索キーワード",
        max_length=190,
        blank=False,
        null=False,
        unique=False,
    )

    tweet_id = models.CharField(
        'ツイートID',
        # フォームから入力する際に入力必須にするかどうか
        max_length=190,
        blank=False,
        # nullをOKにするかどうかだがCharFieldだと空文字が入るからTrueにはしない
        null=False,
        unique=False,)
    
    user_id = models.CharField(
        'ユーザーID',
        max_length=190,
        unique=False,)
    
    user_name = models.CharField(
        'ユーザー名',
        max_length=190,
        unique=False,)
    
    text = models.TextField(
        'ツイート内容',
        blank=True,
        null=True,)
    
    favorite = models.PositiveIntegerField(
        verbose_name='いいね数',)

    retweet = models.PositiveIntegerField(
        verbose_name='リツイート数',)


    created_at = models.DateTimeField(
        verbose_name='ツイート日時',)
    
    loaded_at = models.DateTimeField(
        verbose_name='データ取得日',
        auto_now_add=True)
    
    # 複合ユニークの設定
    class Meta:
        constraints = [
            models.UniqueConstraint(
                fields=["keyword","tweet_id"],
                name = "tweet_unique"
            )
        ]

    # def __str__(self)により、管理画面に表示されるモデル内のデータを判別するための、名前を定義することができる    
    def __str__(self):
        return self.text[:10]


ここで再度CONVERT TO CHARACTER SET を実行してみます。
(tweepy_test_tweetsがテーブル名です)

ALTER TABLE tweepy_test_tweets CONVERT TO CHARACTER SET utf8mb4;

↓文字コードがutf8mb4に変更されました!

| tweepy_test_tweets | CREATE TABLE `tweepy_test_tweets` (
  `id` bigint(20) NOT NULL AUTO_INCREMENT,
  `tweet_id` varchar(190) NOT NULL,
  `user_id` varchar(190) NOT NULL,
  `user_name` varchar(190) NOT NULL,
  `text` longtext,
  `favorite` int(10) unsigned NOT NULL,
  `retweet` int(10) unsigned NOT NULL,
  `created_at` datetime(6) NOT NULL,
  `loaded_at` datetime(6) NOT NULL,
  `keyword` varchar(190) NOT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `tweet_unique` (`keyword`,`tweet_id`)
) ENGINE=InnoDB AUTO_INCREMENT=344 DEFAULT CHARSET=utf8mb4 |


実際にツイートを取得して保存してみます。

絵文字付きで保存できました!!

元々は絵文字の処理のためにコードが長くなってしまっていたので、それが短くなって少しコードがすっきりしました。


設定変更などをやってみると理解が深まっていいですね。
ここまでお読みいただきありがとうございました!


参考


この記事が気に入ったらサポートをしてみませんか?