"""YouTube Studio の「詳細モード」から書き出した ZIP(2026-09-29〜2026-10-27)を読み、 チャンネルの見直しに使った数字を出す。 使い方: python3 analyze_youtube.py ZIP の中身は 表データ.csv・合計.csv・グラフデータ.csv。どの ZIP がどの表かは、 表データ.csv の1行目(見出し)で見分ける。 """ import csv, io, sys, zipfile from collections import defaultdict from pathlib import Path def read_zip(path): out = {} with zipfile.ZipFile(path) as z: for info in z.infolist(): raw = info.filename try: name = raw.encode("cp437").decode("utf-8") except (UnicodeEncodeError, UnicodeDecodeError): name = raw text = z.read(info).decode("utf-8-sig") out[name] = list(csv.reader(io.StringIO(text))) return out def sec(hms): if not hms: return 0 h, m, s = (int(x) for x in hms.split(":")) return h * 3600 + m * 60 + s def num(x): try: return float(x) except (TypeError, ValueError): return 0.0 folder = Path(sys.argv[1]) tables = {} for z in sorted(folder.glob("*.zip")): files = read_zip(z) head = files["表データ.csv"][0][0] tables[head] = files print("読んだ表:", ", ".join(tables)) print() # 1. ショートと本編の比べ t = tables["コンテンツ タイプ"]["表データ.csv"] print("## 1. コンテンツタイプ別(視聴回数・総再生時間・YouTube が出す平均視聴時間)") for row in t[1:]: print(" ", row) for row in t[2:]: kind, views, hours, avg = row[0], num(row[1]), num(row[2]), sec(row[3]) per_start = hours * 3600 / views if views else 0 engaged = hours * 3600 / avg if avg else 0 print(f" {kind}: 総再生時間÷視聴回数 = {per_start:.1f}秒 / YouTube の平均視聴時間 = {avg}秒" f" → 平均視聴時間で割った回数 ≒ {engaged:,.0f} 回(視聴回数 {views:,.0f} の {engaged / views:.0%})") print() # 2. 動画ごと(ショート/本編) t = tables["コンテンツ"]["表データ.csv"] head = t[0] rows = [dict(zip(head, r)) for r in t[1:] if r[0] != "合計"] for r in rows: r["秒"] = num(r["長さ"]) r["回"] = num(r["視聴回数"]) r["時間"] = num(r["総再生時間(単位: 時間)"]) r["表示"] = num(r["サムネイルのインプレッション"]) r["率"] = r["サムネイルのクリック率 (%)"] r["登録"] = num(r["チャンネル登録者"]) r["平均秒"] = r["時間"] * 3600 / r["回"] if r["回"] else 0 shorts = [r for r in rows if r["秒"] <= 60] longs = [r for r in rows if r["秒"] > 60] for label, group in (("ショート", shorts), ("本編", longs)): print(f"## 2. {label}: {len(group)}本 / 視聴 {sum(r['回'] for r in group):,.0f} / " f"表示 {sum(r['表示'] for r in group):,.0f} / 登録 {sum(r['登録'] for r in group):,.0f}") print() print("## 3. 本編の動画ごと(表示の多い順)") total_imp = sum(r["表示"] for r in longs) acc = 0 for r in sorted(longs, key=lambda r: -r["表示"]): acc += r["表示"] pct = r["平均秒"] / r["秒"] * 100 if r["秒"] else 0 print(f" 表示 {r['表示']:>5.0f}(累計 {acc / total_imp:5.1%}) クリック率 {r['率'] or '-':>5} 視聴 {r['回']:>4.0f}" f" 平均 {r['平均秒']:>5.1f}秒/{r['秒']:.0f}秒({pct:4.1f}%) 登録 {r['登録']:.0f} {r['動画のタイトル']}") top4 = sum(sorted((r["表示"] for r in longs), reverse=True)[:4]) print(f" 上位4本の表示 {top4:,.0f} / 本編全体 {total_imp:,.0f} = {top4 / total_imp:.1%}") print(f" 表示160回以下の本編: {sum(1 for r in longs if r['表示'] <= 160)}本") print() print("## 4. ショートの動画ごと(視聴の多い順)") for r in sorted(shorts, key=lambda r: -r["回"]): print(f" 視聴 {r['回']:>5.0f} 総再生時間÷視聴 {r['平均秒']:>5.1f}秒/{r['秒']:.0f}秒 登録 {r['登録']:.0f}" f" 表示 {r['表示']:.0f} {r['動画のタイトル']} ({r['動画公開時刻']})") print() # 5. 上位10本のショート: Studio の概要の画面に出ていた平均視聴時間(YouTube の値)と比べる studio_avg = { # 概要の画面「この期間の上位コンテンツ」の平均視聴時間(秒)。画面写真から書き写した値 "中国は1日120億円、日本は? 比べる前に確かめたいこと": 26, "人型ロボット、乗っ取れる? 研究者の実験と本物の被害": 23, "人を18mにしたら、何トン? #Shorts": 20, "「1秒でも早く」と頼んだら、ロボットは最速モード?": 24, "横浜のガンダム、歩けないの? #Shorts": 16, "スーパーの冷凍庫にサイバー攻撃、温度が変わったのは本物の機械": 15, "AIのセキュリティ製品、入れる前に何を聞く?": 13, "赤字89億円、全員ロボットにしたら埋まる? ジャングリア沖縄で勝手に試算": 13, "病院のパイプで血液を速く送ると、壊れる?": 14, "ガンダムは無理、と証明できる? #Shorts": 14, } print("## 5. 上位10本のショート: 総再生時間÷視聴回数 と YouTube の平均視聴時間の比(すぐスワイプされなかった割合の目安)") for r in shorts: a = studio_avg.get(r["動画のタイトル"]) if a: print(f" {r['平均秒']:>5.1f}秒 / {a}秒 = {r['平均秒'] / a:4.0%} {r['動画のタイトル']}") print() # 6. 日ごとの視聴(コンテンツタイプ別) g = tables["コンテンツ タイプ"]["グラフデータ.csv"] daily = defaultdict(dict) for d, kind, v in g[1:]: daily[d][kind] = int(num(v)) print("## 6. 日ごとの視聴(ショート / 本編)") for d in sorted(daily): if d >= "2026-10-12": print(f" {d} ショート {daily[d].get('YouTube ショート', 0):>6} 本編 {daily[d].get('動画', 0):>4}") print() # 7. 流入・登録・終了画面・再生リスト・投稿 for key in ("トラフィック ソース", "チャンネル登録元", "終了画面要素", "再生リスト", "投稿", "新しい視聴者とリピーター", "視聴行動別の視聴者区分", "チャンネル登録状況"): print(f"## 7. {key}") for row in tables[key]["表データ.csv"]: print(" " + " | ".join(row)) print()