概要
Obsidianのようなマークダウンエディタは、表も扱えるが、長文を含む表は横幅の問題があって読みにくい。
逆に、アウトラインのおかげで縦に長いのは問題になりにくいので、CSVファイルの内容を読み込み、各レコードとフィールドをMarkdownの見出しとして構造化されたテキストに変換するPythonコードを作成した。
今回のコードでできること
以下のようなcsvを
Name,Age,City,Occupation
Alice,30,New York,Engineer
Bob,24,London,Designer
Charlie,35,Paris,Doctor
David,,Tokyo,
Eve,29,Sydney,Artist
以下のようなマークダウンテキストにする
# Record 1
## Name
Alice
## Age
30
## City
New York
## Occupation
Engineer
---
# Record 2
## Name
Bob
## Age
24
## City
London
## Occupation
Designer
---
# Record 3
## Name
Charlie
## Age
35
## City
Paris
## Occupation
Doctor
---
# Record 4
## Name
David
## City
Tokyo
---
# Record 5
## Name
Eve
## Age
29
## City
Sydney
## Occupation
Artist
ソースコード
input_csv_fileとoutput_markdown_fileは適宜変更する
import csv
import os
def csv_to_structured_markdown(file_path: str, record_separator: str = "---") -> str:
"""
CSVファイルを読み込み、各レコードをレベル1の見出し、各フィールドをレベル2の見出しで構造化します。
フィールドが空の場合、その見出しと内容はスキップされます。
Args:
file_path (str): 変換したいCSVファイルのパス。
record_separator (str): 各レコードの出力ブロック間に挿入するセパレータ文字列。
Noneまたは空文字列の場合、セパレータは挿入されません。
Returns:
str: 構造化されたマークダウン文字列。
ファイルが存在しない場合や内容が空の場合は、エラーメッセージを含む文字列を返します。
"""
try:
with open(file_path, 'r', newline='', encoding='utf-8') as f:
reader = csv.reader(f)
try:
header = next(reader) # ヘッダー行を取得
except StopIteration:
return f"エラー: CSVファイル '{file_path}' はヘッダー行を含まないか、空です。"
markdown_lines = []
record_num = 0
for row_index, row in enumerate(reader):
record_num += 1
# 2つ目以降のレコードの前にセパレータを追加
if record_num > 1 and record_separator:
markdown_lines.append(record_separator)
markdown_lines.append("") # セパレータの後に空行を挿入して見やすく
# レコードの開始をレベル1の見出しで示す
markdown_lines.append(f"# Record {record_num}")
markdown_lines.append("") # 見出しの後に空行を入れる
# 各フィールドをレベル2の見出しと内容で表示
for col_idx, header_name in enumerate(header):
# データ行の列数がヘッダーより短い場合も考慮し、空文字列として扱う
field_value = row[col_idx] if col_idx < len(row) else ""
# 値が空でなければマークダウン形式で追加
# .strip() で空白のみの文字列も空と判定
if field_value.strip():
markdown_lines.append(f"## {header_name}")
markdown_lines.append(f"{field_value}")
markdown_lines.append("") # 各見出し-内容ペアの後に空行を入れる
if not markdown_lines and record_num == 0:
return f"エラー: CSVファイル '{file_path}' はヘッダーのみでデータ行がありません。"
elif not markdown_lines and record_num > 0: # ヘッダーはあるが、すべてのデータフィールドが空だった場合
return f"注意: CSVファイル '{file_path}' にはデータ行がありますが、すべてのフィールドが空でした。"
return "\n".join(markdown_lines).strip() # 末尾の余分な改行を削除
except FileNotFoundError:
return f"エラー: 指定されたファイル '{file_path}' が見つかりません。"
except Exception as e:
return f"CSVの読み込み中にエラーが発生しました: {e}"
# --- メイン処理 ---
if __name__ == "__main__":
input_csv_file = "test.csv"
output_markdown_file = "output.md"
# CSVをマークダウンに変換
print(f"'{input_csv_file}' を '{output_markdown_file}' に変換しています...")
markdown_output = csv_to_structured_markdown(input_csv_file)
# マークダウン出力をファイルに保存
with open(output_markdown_file, 'w', encoding='utf-8') as f:
f.write(markdown_output)
print(f"変換が完了しました。結果は '{output_markdown_file}' に保存されました。")
print("\n--- 'output.md' の内容プレビュー ---")
print(markdown_output)
print("----------------------------------\n")