py-py’s blog

何か書くよ

Pythonによる文字データの圧縮

DBにデータを入れる際に、データが大きすぎてinsertできなかったため、データを圧縮して保存することにした。
方法は簡単で、以下のようになる

その前にいくつかまとめる

  • .encode()
  • .decode()
  • .hex()
  • .fromhex()

encode()の使い方

文字列をbytes型へ変換するために利用する

string.encode("utf-8")

decode()の使い方

bytesクラスを文字列型へ変換するために利用する

bytes.decode("utf-8")

それぞれ以下になる

s = "この木何の木"
sen = "この木何の木".encode("utf-8")
print(s) # この木何の木
print(sen) # b'\xe3\x81\x93\xe3\x81\xae\xe6\x9c\xa8\xe4\xbd\x95\xe3\x81\xae\xe6\x9c\xa8'
ds = sen.decode("utf-8")
print(ds) # この木何の木

hex()の使い方

bytesクラスを16進表記の文字列型へ変換するために利用する

bytes.hex()

fromhex()の使い方

16進表記の文字列をbytes型へ変換する

bytes.fromhex("16進表記文字列")

docs.python.org

圧縮の話

import bz2

message = "この木何の木木になる木になる名前も知らない木ですから"
print(f"長さ:{len(message)} 中身:{message}")
# 長さ:26 中身:この木何の木木になる木になる名前も知らない木ですから

# 圧縮を行う
# bytes型に変えた文字列を、compress()により圧縮する
message_test = bz2.compress(message.encode("utf-8"))
print(f"長さ:{len(message_test)} 中身:{message_test}")
#  長さ:86 中身:b'BZh91AY&SY\xb874\x16\x00\x00\x1b\x00y4*J$\x82\xd9\x00\x02\x0f\x80 \x00P\xa0\xd1\xa3A\x90\x1a\r\x1a\x9a\x804hxS\xe4\x00\x13\x04\x15\x19j\xcc\xeb(+\x16\xc2\x05D\xa8\xf7\x87\x83 \x87\x88\x89\xdcf\xcd+j\x13\xf8\xbb\x92)\xc2\x84\x85\xc1\xb9\xa0\xb0'

# compress()により圧縮したbytesをhex()により16進表記の文字列にする
m = message_test.hex()
print(f"長さ:{len(m)} 中身:{m}")
# 長さ:172 中身:425a6839314159265359b837341600001b0079342a4a2482d900020f80200050a0d1a341901a0d1a9a8034687853e400130415196acceb282b16c20544a8f7878320878889dc66cd2b6a13f8bb9229c28485c1b9a0b0'

# ここからは逆変換
# 16進表記の文字列からbytes型へ変換する
bm = bytes.fromhex(m)
print(f"長さ:{len(bm)} 中身:{bm}")
# 長さ:86 中身:b'BZh91AY&SY\xb874\x16\x00\x00\x1b\x00y4*J$\x82\xd9\x00\x02\x0f\x80 \x00P\xa0\xd1\xa3A\x90\x1a\r\x1a\x9a\x804hxS\xe4\x00\x13\x04\x15\x19j\xcc\xeb(+\x16\xc2\x05D\xa8\xf7\x87\x83 \x87\x88\x89\xdcf\xcd+j\x13\xf8\xbb\x92)\xc2\x84\x85\xc1\xb9\xa0\xb0'

# 圧縮したものをもとに戻す
bmm = bz2.decompress(bm)
print(f"長さ:{len(bmm)} 中身:{bmm}")
# 長さ:78 中身:b'\xe3\x81\x93\xe3\x81\xae\xe6\x9c\xa8\xe4\xbd\x95\xe3\x81\xae\xe6\x9c\xa8\xe6\x9c\xa8\xe3\x81\xab\xe3\x81\xaa\xe3\x82\x8b\xe6\x9c\xa8\xe3\x81\xab\xe3\x81\xaa\xe3\x82\x8b\xe5\x90\x8d\xe5\x89\x8d\xe3\x82\x82\xe7\x9f\xa5\xe3\x82\x89\xe3\x81\xaa\xe3\x81\x84\xe6\x9c\xa8\xe3\x81\xa7\xe3\x81\x99\xe3\x81\x8b\xe3\x82\x89'

# 最後にbytes型を文字列に戻す
bmmm = bmm.decode("utf-8")
print(f"長さ:{len(bmmm)} 中身:{bmmm}")
#  長さ:26 中身:この木何の木木になる木になる名前も知らない木ですから

今回はテキストの長さが短いため、圧縮したといっても却って長くなってはいるが
これがもう少し大きいデータだと短縮される。