1. 程式人生 > 實用技巧 >解決Python插入資料到MySQL時遇到的Incorrect string value錯誤

解決Python插入資料到MySQL時遇到的Incorrect string value錯誤

問題與原因

使用python執行插入語句將資料插入到MySQL時丟擲了以下異常

pymysql.err.InternalError: (1366, "Incorrect string value: '\\xF0\\x9F\\x91\\x8D, ...' for column 'content' at row 1")

以上錯誤是由編碼問題造成的,你使用的資料庫預設編碼是utf8,可以儲存1到3個位元組,但是你插入到資料庫中的字串包含emoji表情字元(佔用4個位元組),因此會丟擲Incorrect string value異常。

解決方法

解決的方法主要有以下兩種

  1. 修改MySQL的編碼格式
  2. 在程式中過濾emoji表情字元

修改MySQL的編碼格式

MySQL從5.5.3版本開始,才支援4個位元組的utf8編碼,編碼名稱是utf8mb4(mb4意思為max bytes 4),在MySQL中執行以下SQL語句可以看到utf8和utf8mb4的相關資訊

SELECT * FROM information_schema.CHARACTER_SETS 
WHERE CHARACTER_SET_NAME LIKE 'utf8%'

結果如下

CHARACTER_SET_NAME DEFAULT_COLLATE_NAME DESCRIPTION MAXLEN
utf8 utf8_general_ci UTF-8 Unicode 3
utf8mb4 utf8mb4_general_ci UTF-8 Unicode 4

因此,將MySQL編碼改為utf8mb4就可以解決這個問題。

解決程式的編碼問題需要進行以下幾個操作:

  1. 修改my.cnf配置

    找到MySQL的配置檔案my.cnf(windows系統一般在MySQL的安裝目錄中,linux系統放在/etc目錄下)

    修改含有utf8編碼的引數為utf8mb4,如下

    character-set-server=utf8mb4
    
    [client]
    default-character-set=utf8mb4
    
    [mysql]
    default-character-set=utf8mb4
    

    修改儲存後,重啟MySQL。

  2. 修改資料庫和資料表的編碼格式

    修改資料庫編碼(更改db_name為你的資料庫)

    ALTER DATABASE `db_name` CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci; 
    

    修改資料表編碼(更改table_name為你的資料表)。

    ALTER TABLE `table_name` CONVERT TO CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci;
    
  3. 修改python連線pymysql的配置資訊

    去掉charset引數或將charset引數設定為utf8mb4,如:

    MYSQL_CONFIG = {
        'host': 'localhost',  # IP地址
        'port': 3306,  # 埠
        'user': 'root',  # 使用者名稱
        'passwd': '123456',  # 密碼
        'db': 'mydb',  # 資料庫
        # 'charset': 'utf8mb4',  # 字元編碼
    }
    

再次執行你的程式就可以正常插入資料了。

在程式中過濾emoji表情字元

為了避免出現以上錯誤,我們還可以在插入資料前對資料進行清洗,過濾掉文字中的emoji表情字元,再將資料插入到表中。

要去掉文字中的emoji表情字元可以使用以下兩種方法

自定義清除方法

def filter_emoji(desstr,restr=''):  
    #過濾表情   
    try:  
        co = re.compile(u'[\U00010000-\U0010ffff]')  
    except re.error:  
        co = re.compile(u'[\uD800-\uDBFF][\uDC00-\uDFFF]')  
    return co.sub(restr, desstr)

插入資料前先執行以上方法過濾emoji表情,如

content = '