Python:音楽ファイル名から曲名だけを抽出する

Python:音楽ファイル名から曲名だけを抽出するPython
スポンサーリンク

Pythonを使って「01 ハレ晴レユカイ.mp3」のような音楽ファイル名から、「ハレ晴れユカイ」のように曲名だけを抽出する方法。

スポンサーリンク

考え方

1.元ファイル名を拡張子部分その他の部分2分割
2.先頭についているであろう曲番号の数値を取って曲名だけを抽出する

拡張子部分とその他の部分に2分割

まずは、元のファイル名から拡張子部分を取り除くため2分割する。

例)
元ファイル名: 01 ハレ晴れユカイ.mp3

2分割イメージ

その他部分01 ハレ晴れユカイ
拡張子部分.mp3

曲番号の数値を取って曲名だけを抽出

拡張子部分を取り出したファイル名の前半部分は、アルバムの曲番号(上記の「01 」のような番号)がついていたりする場合が多い。
調べたところ、「1-01」のように数値のあと「-」(ハイフン)+数値である場合もあった。
いずれの場合も番号のあと半角スペースが1つくっついて曲名へとつづいていた。

そこで、正規表現を使って、先頭の数字部分+1文字の空白を検索して抜き出し、最後に

ハレ晴れユカイ

のように曲名のみ抽出する。

イメージとしては、こんな感じ。
Python:音楽ファイル名から曲名だけを抽出する

プログラムの解説

拡張子部分とその他部分に2分割するのは、割と簡単。
os.path.splitextを使う。(使用するにはimport os.pathが必要)
この関数、ファイル名を手前部分と拡張子部分とに分けて戻り値をリスト型として返す。
以下ではfrontrearの変数にそれぞれ「その他部分」と「拡張子部分」格納している。

# 拡張子部分を分割
front, rear = os.path.splitext(original)

次に、取り出した手前部分の先頭を取り出す処理。
具体的には、数字部分+1文字の空白を正規表現を使って取り出す。

まずは、先頭数値+1文字の空白のパターンを正規表現で作成。

^[0-9]+ +

実際のファイル名には、「1-01」なる番号もあったので、これも正規表現でパターンを作成。

^[0-9]+-[0-9]+ +

一応解説をすると「^」は先頭を表していて、「[0-9]」は、0~9までの数値パターンを表す。
+」は直前のパターンや文字が1以上連続する場合を意味している。

例として、

[0-9]+

とすると、「10」も「001」も「12345」も同じパターンとして認識される。

半角スペースもこれと同様に「+」をつけてあるため、
「10 」のようにスペースが1つでも、「101  」のようにスペースが複数でも同じパターンとして認識するようにしてある。

実際のPythonプログラムでは、以下のようにパターンを生成した。

# 先頭の番号の正規表現
regexp = re.compile("^[0-9]+ +|^[0-9]+-[0-9]+ +")

今回先頭が、「01」や「1-01」などの2パターンをチェックしたので、「|」記号を使って、AまたはBの場合という判定をしている。

^[0-9]+ +|^[0-9]+-[0-9]+ +

次に作成したパターンを利用して文字列チェックを行いパターンに合致した文字列を取り出す。
search関数を使って取り出しているため、戻り値はマッチオブジェクトという型。(文字列が返るわけではない点に注意)
見つからない場合は、「None」が返る。これはif文で判定可能。

ちなみにsearch関数以外にfindallという関数もある。search関数は、見つかった最初のマッチオブジェクトを返すのに対して、findallは、見つかったすべてのマッチオブジェクトを返す。したがって今回は、search関数を利用した。

# 先頭の番号+半角スペースの部分をマッチオブジェクトとしてheadに返す
head = regexp.search(front)

最後に取り出した数値文字列部分をreplace関数で空欄に置き換えて曲名だけを抽出する。
replace関数の引数部分にhead.group()を指定しているのは、マッチオブジェクトの戻り値headはあくまで文字列ではないため。実際にマッチした文字列は戻り値であるheadを使いhead.group()で参照する必要がある。

filename = front.replace(head.group(), "")  # 空欄に置き換えて曲名のみを抽出

ここまでで問題なかったのだが、わたしが個人的に所有している音楽ファイルには、先頭に番号がついていない「優しい忘却.mp3」のようなファイル(どっから持ってきたのだ??)もあったため、最後に以下の対処をした。

if head is None:    # 先頭の番号がない場合
	filename = front
else:               # 先頭の番号がある場合
	filename = front.replace(head.group(), "")  # 空欄に置き換えて曲名のみを抽出

以下に今回のソースコード全体と実行イメージを示す。

ソースコード全体と実行イメージ

bunkatu.py

# -*- charset: utf-8 -*-
"""
	音楽ファイル名から曲名だけを抽出する
		
		ex)	[01 ハレ晴レユカイ.mp3] 	-----> [ハレ晴レユカイ]
				[1-01 止マレ!.m4a] 		-----> [止マレ!]
"""
import os.path
import re

# 元のファイル名
originals = ["01 ハレ晴レユカイ.mp3", "02 God knows....m4a", "1-01 止マレ!.m4a", "優しい忘却.mp3"]

for original in originals:
	print(original+"\n")
	# 拡張子部分を分割
	front, rear = os.path.splitext(original)
	print("\t[{0}]+[{1}]\n".format(front, rear))

	# 先頭の番号の正規表現(先頭文字が1-01や05の場合)
	regexp = re.compile("^[0-9]+ +|^[0-9]+-[0-9]+ +")

	# 先頭の番号+半角スペースの部分をマッチオブジェクトとしてheadに返す
	head = regexp.search(front)

	if head is None:    # 先頭の番号がない場合
		filename = front
	else:               # 先頭の番号がある場合
		filename = front.replace(head.group(), "")  # 空欄に置き換えて曲名のみを抽出

	# 抽出したファイル名を表示
	print("\t[{0}]\n".format(filename))

実行イメージ

01 ハレ晴レユカイ.mp3

[01 ハレ晴レユカイ]+[.mp3]

[ハレ晴レユカイ]

02 God knows….m4a

[02 God knows…]+[.m4a]

[God knows…]

1-01 止マレ!.m4a

[1-01 止マレ!]+[.m4a]

[止マレ!]

優しい忘却.mp3

[優しい忘却]+[.mp3]

[優しい忘却]

以上、Pythonを使って音楽ファイル名から曲名だけを抽出するでした。お役に立てば幸いです。

参考文献
ファイル名の名前と拡張子をPythonで分けてみた – https://cortyuming.hateblo.jp/entry/20090528/p1

Pythonドキュメント 7.2. re — 正規表現操作 – https://docs.python.org/ja/2.7/library/re.html

コメント