in my 雑記

プログラミング bump 日々のことなど

python3でテキストファイルからデータベース(sqlite3)に取り込む

f:id:inmyzakki:20170902164248p:plain

はじめに

今回はテキストファイルをsqlite3に取り込む方法を紹介します。
DBはsqlite3を使用しました。
ちょっとした、データ分析のために使用する予定なので、
単一ファイルで管理が楽なsqlite3を選択しました。
今回は例として歌詞のテキストデータをデータベースに取り込みたいと思います。

準備

まずは取り込むテキストのサンプルを作ります。
下記を「test.txt」として保存します。

In my nikke

歌手 BUMP OF CHICKEN
作詞 Motoo Fujiwara
作曲 Motoo Fujiwara

俺とヒロは夢の中
ヒロは俺の友達さ
それをバンプが邪魔をした
ヒロと俺は離れ離れ
ヒロのハートに突き刺され(突き刺され)

次に取り込むデータを入れるためのDBを作成します。
DBアクセスツールとしてDB Browser for SQLiteを使用するため、
ダウンロードしてインストールします。

起動して、New Databaseでデータベースを作成します。
f:id:inmyzakki:20170516224502p:plain 今回dbの名前は「music」とします。
作成したら、テーブルを作成する画面が表示されます。
サンプルテキストの情報を取り込みたいので、
今回は以下のようなテーブルを作りました。
f:id:inmyzakki:20170516224725p:plain

CREATE TABLE `artist_song_lyrics` ( `seq` INTEGER NOT NULL, `artist` TEXT NOT NULL, `song` TEXT NOT NULL, `sakushi` TEXT, `sakkyoku` TEXT, `lyrics` TEXT NOT NULL, PRIMARY KEY(`seq`) )

カラムは以下の内容です。

seq:シークエンス(連番)  
artist:アーティスト名  
song:曲名  
sakushi:作詞家  
sakkyoku:作曲家  
lyrics:歌詞  

本当は正規化をした方がいいのですが、今回はめんどくさいのでやりません。
正規化しない方がSQLは簡単にかけるし、速度追わないなら正規化いらないですね。

プログラム

ファイル取り込みプログラム「main.py」。
今回拡張性を考えて、データベースを触る処理はDatabaseOpeとしてクラス化した。
歌詞データは同じフォーマットで来ることを想定して、
行数を見て、各種データを取り出している。(なんか、バカっぽいやり方だなぁ) ファイルオープンモジュールは文字コードエラーが怖いのでcodecsを使った。
seqは曲を複数取り込むことを想定して、DBを見てから付番するようにしている。

# -*- coding: utf-8 -*-
#ライブラリインポート
import DatabaseOpe
import io
import os
import sys
import codecs
import linecache

#設定値
dbName = "music.db"
textName = "test.txt"

#デフォルトエンコードをutf-8にする。
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')

#データベース読み込み
DBpath = os.path.normpath(os.path.join(os.path.abspath(__name__),'../')) + '/' + dbName
DB = DatabaseOpe.DatabaseOpe(DBpath)

#ファイル読み込み
f = codecs.open(textName, 'r', 'utf-8')
lines2 = f.readlines() # 1行毎にファイル終端まで全て読む(改行文字も含まれる)
f.close()

#変数宣言
lyrics = ""

#行ごとに読み取り
for i,line in enumerate(lines2):
    # print(i)
    if i == 0:
        song = line.replace('\n','')
    elif i == 2:
        artist = line.replace('\n','')
    elif i == 3:
        sakushi = line.replace('\n','')
    elif i == 4:
        sakkyoku = line.replace('\n','')
    elif i > 5:
        lyrics = lyrics + line.replace('\n','').replace('\r','') + '\n'

#文字整形
lyrics = lyrics[:-2]
artist = artist[3:]
sakushi = sakushi[3:]
sakkyoku = sakkyoku[3:]

#DBインサート
DB.insertArtist(DB.getArtistSeq(),artist,song,sakushi,sakkyoku,lyrics)

データベース操作クラス「DatabaseOpe.py」。
今回はここにSQLをベタ書きした。
個人的にはsqlは専用のテーブルを作って、DB内で管理した方が管理しやすいと思う。

# -*- coding: utf-8 -*-
import sqlite3
import datetime

class DatabaseOpe:
    def __init__(self,DBpath):
        self.con = sqlite3.connect(DBpath, isolation_level=None)
        self.cur = self.con.cursor()

    # ファイルテーブルseq取得処理
    def getArtistSeq(self):
        self.cur.execute("select max(seq) from artist_song_lyrics;")
        seq = self.getSeqInc(self.cur.fetchall()[0])
        return seq

    # インサート処理
    def insertArtist(self,seq,artist,song,sakushi,sakkyoku,lyrics):
        self.cur.execute("insert into artist_song_lyrics (seq,artist,song,sakushi,sakkyoku,lyrics) values (?,?,?,?,?,?);",(seq,artist,song,sakushi,sakkyoku,lyrics))

おわり

今回は機械学習や統計処理をするときに、よく使うであろうファイル操作とDB操作を行った。
ちょっとした、データ分析とかでデータの取り扱いをするならsqliteが便利です。