Spaces:
Sleeping
Sleeping
File size: 6,586 Bytes
568bbca c0206de 5733dea 723ba3b 5733dea 723ba3b 568bbca c0206de 5733dea c0206de 5733dea c0206de 5733dea ce36f11 568bbca c0206de 568bbca ecf9952 c0206de 568bbca 723ba3b 5733dea 723ba3b c0206de 723ba3b c0206de 568bbca c0206de 5733dea c0206de 568bbca | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | #!/usr/bin/env python3
"""
CSVからサークルデータのJSONを生成するスクリプト
"""
import os
import sys
import csv
import json
sys.path.append(os.path.abspath(os.path.join(os.path.dirname(__file__), "..")))
from utils.logger import setup_logger
from utils.json import get_file_path_from_config, json_dumps
# --- ロギングの設定 ---
log = setup_logger(__name__)
def parse_bool(value: str) -> bool:
"""文字列をブール値に変換"""
return value.lower() in ("true", "1", "yes")
def parse_int(value: str) -> int | None:
"""文字列を整数に変換(空の場合はNone)"""
if not value or value.strip() == "":
return None
try:
return int(value)
except ValueError:
return None
def parse_list(value: str, delimiter: str = "|") -> list[str]:
"""区切り文字で分割してリストに変換"""
if not value or value.strip() == "":
return []
return [item.strip() for item in value.split(delimiter) if item.strip()]
def parse_json(value: str) -> list | dict | None:
"""JSON文字列をパースする(空の場合はNone、失敗した場合は空リスト)"""
if not value or value.strip() == "":
return None
try:
return json.loads(value)
except json.JSONDecodeError:
log.warning(f"JSONのパースに失敗しました: {value[:50]}...")
return []
def convert_annual_schedule(old_schedule: list | None) -> list | None:
"""
旧形式の年間予定を新形式に変換する。
旧形式: [{"month": 4, "events": ["新歓", "春季リーグ開幕"]}, ...]
新形式: [{"period": "4月", "event": "新歓"}, {"period": "4月", "event": "春季リーグ開幕"}, ...]
"""
if not old_schedule:
return None
new_schedule = []
for item in old_schedule:
# 旧形式(month + events)の場合
if "month" in item and "events" in item:
month = item["month"]
events = item["events"]
period = f"{month}月"
for event in events:
new_schedule.append({"period": period, "event": event})
# 新形式(period + event)の場合はそのまま
elif "period" in item and "event" in item:
new_schedule.append(item)
return new_schedule if new_schedule else None
def main():
"""CSVからサークルデータを読み込み circles.json を生成する。"""
log.info("CSVファイルからサークルデータを読み込みcircles.jsonを生成します。")
input_csv_path = get_file_path_from_config(
"circles.original_csv", "resources/original_circles.csv"
)
output_json_path = get_file_path_from_config(
"circles.circles_json", "data/generated/circles.json"
)
if not os.path.exists(input_csv_path):
log.error(f"入力CSVファイルが見つかりません: {input_csv_path}")
sys.exit(1)
circles = []
try:
with open(input_csv_path, "r", encoding="utf-8") as f:
reader = csv.DictReader(f)
for row in reader:
# 画像データのパース
images_data = parse_json(row.get("images", ""))
images = images_data if images_data else []
# mainImage の決定: images配列の最初の画像(order=0)を使用
main_image = None
if images:
# order=0 の画像を探す
for img in images:
if img.get("order", 0) == 0:
main_image = img
break
# order=0 がなければ最初の画像を使用
if main_image is None:
main_image = images[0]
# SNSデータのパース(handleフィールドを含む)
sns_data = parse_json(row.get("sns", ""))
sns = []
if sns_data:
for sns_item in sns_data:
sns.append({
"type": sns_item.get("type", ""),
"url": sns_item.get("url", ""),
"handle": sns_item.get("handle")
})
# 年間予定のパース(新形式に変換)
annual_schedule_data = parse_json(row.get("annualSchedule", ""))
annual_schedule = convert_annual_schedule(annual_schedule_data)
circle = {
"circleId": row.get("circleId", ""),
"circleName": row.get("circleName", ""),
"circleNameKana": row.get("circleNameKana", ""),
"projectId": row.get("projectId") or None,
"projectName": row.get("projectName") or None,
"genre": row.get("genre") or None,
"areaCode": row.get("areaCode") or None,
"pamphletNumber": parse_int(row.get("pamphletNumber", "")),
"shortIntro": row.get("shortIntro") or None,
"detailDescription": row.get("detailDescription") or None,
"memberCount": parse_int(row.get("memberCount", "")),
"memberNote": row.get("memberNote") or None,
"activityFrequency": row.get("activityFrequency") or None,
"activityFrequencyNote": row.get("activityFrequencyNote") or None,
"activityLocation": row.get("activityLocation") or None,
"annualFee": parse_int(row.get("annualFee", "")),
"otherCosts": row.get("otherCosts") or None,
"annualSchedule": annual_schedule,
"contactInfo": row.get("contactInfo") or None,
"websiteUrl": row.get("websiteUrl") or None,
"isArchived": parse_bool(row.get("isArchived", "false")),
"images": images,
"mainImage": main_image,
"sns": sns,
}
circles.append(circle)
except Exception as exc:
log.error(f"CSVファイルの読み込みに失敗しました: {exc}")
sys.exit(1)
os.makedirs(os.path.dirname(output_json_path), exist_ok=True)
json_dumps(circles, output_json_path)
log.info(f"サークルデータの生成が完了しました: {output_json_path} ({len(circles)}件)")
sys.exit(0)
if __name__ == "__main__":
main()
|