File size: 4,833 Bytes
024b30f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3a0e812
024b30f
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import pandas as pd
import os

# --- クラウド環境用のシンプルなパス設定 ---
FILE_PATH = "VTuber_Ultimate_Database.csv"
OUTPUT_DIR = "output"
os.makedirs(OUTPUT_DIR, exist_ok=True)

# データの読み込み
try:
    df = pd.read_csv(FILE_PATH)
    unique_ids = sorted(df['ハンドル(ID)'].dropna().unique().tolist())
    categories = sorted(df['カテゴリ'].dropna().unique().tolist())
    status_msg = f"正常: {len(df)}件のレコードをデータベースから読み込みました。"
except Exception as e:
    df = pd.DataFrame()
    unique_ids, categories = [], []
    status_msg = f"エラー: データベースが見つかりません。"

# --- コアロジック ---
def filter_and_export(handles, cats, keyword_in, keyword_ex, min_views, min_date, max_results):
    if df.empty:
        return None, None, "エラー: データベースが空、または未接続です。"
        
    filtered = df.copy()

    if handles:
        filtered = filtered[filtered['ハンドル(ID)'].isin(handles)]
    if cats:
        filtered = filtered[filtered['カテゴリ'].isin(cats)]
    if keyword_in:
        filtered = filtered[filtered['動画タイトル'].str.contains(keyword_in, case=False, na=False)]
    if keyword_ex:
        filtered = filtered[~filtered['動画タイトル'].str.contains(keyword_ex, case=False, na=False)]
        
    filtered = filtered[filtered['総再生数'] >= min_views]
    if min_date:
        filtered = filtered[filtered['投稿日'] >= min_date]

    filtered = filtered.sort_values('総再生数', ascending=False).head(max_results)

    txt_content = f"【VTuber市場動向 解析レポート】\n"
    txt_content += f"出力日時: {pd.Timestamp.now().strftime('%Y-%m-%d %H:%M:%S')}\n"
    txt_content += f"抽出レコード数: {len(filtered)}件\n"
    txt_content += "=" * 50 + "\n\n"
    
    for _, row in filtered.iterrows():
        txt_content += f"[{row['ハンドル(ID)']}] {row['動画タイトル']}\n"
        txt_content += f"カテゴリ: {row['カテゴリ']} | 総再生数: {row['総再生数']:,} | 高評価数: {row['高評価数']:,}\n"
        txt_content += f"投稿日: {row['投稿日']} | URL: {row['動画URL']}\n"
        txt_content += "-" * 50 + "\n"

    output_path = os.path.join(OUTPUT_DIR, "Market_Analysis_Report.txt")
    with open(output_path, "w", encoding="utf-8") as f:
        f.write(txt_content)

    return filtered, output_path, f"処理完了: {len(filtered)}件のデータを抽出・出力しました。"

custom_css = """
.gradio-container input, .gradio-container textarea, .gradio-container select {
    border: 1px solid #777 !important;
    border-radius: 4px !important;
}
"""

# --- UI構築 ---
with gr.Blocks(title="VT-Analytics Pro") as app:
    gr.Markdown("## VTuber市場解析システム (VT-Analytics Pro)")
    gr.Markdown("検索条件を指定し、データ抽出およびレポート出力(txt形式)を実行してください。")
    gr.Markdown(f"**システムステータス:** {status_msg}")

    with gr.Row():
        with gr.Column(scale=1):
            in_handles = gr.Dropdown(choices=unique_ids, multiselect=True, label="対象ID指定 (複数選択可・空欄で全件)")
            in_cats = gr.CheckboxGroup(choices=categories, value=categories, label="コンテンツ種別")
            in_kw_in = gr.Textbox(placeholder="例: 歌ってみた", label="抽出キーワード (含む)")
            in_kw_ex = gr.Textbox(placeholder="例: 初音ミク", label="除外キーワード (含まない)")
            
            with gr.Row():
                in_min_views = gr.Number(value=100000, label="最低再生数")
                in_min_date = gr.Textbox(value="2024-01-01", label="抽出基準日 (YYYY-MM-DD以降)")
                
            in_max_res = gr.Slider(minimum=10, maximum=2000, value=1000, step=10, label="最大出力件数制限 (AI解析用)")

            search_btn = gr.Button("データ抽出実行", variant="primary")

        with gr.Column(scale=2):
            out_msg = gr.Textbox(label="実行ログ", interactive=False)
            out_file = gr.File(label="解析レポート (.txt) ダウンロード", interactive=False)
            out_df = gr.Dataframe(label="データプレビュー", interactive=False)

    search_btn.click(
        fn=filter_and_export,
        inputs=[in_handles, in_cats, in_kw_in, in_kw_ex, in_min_views, in_min_date, in_max_res],
        outputs=[out_df, out_file, out_msg]
    )

if __name__ == "__main__":
    # 🌟 ここがパスワード設定です。Brainの購入者に教えるIDとパスワードになります。
    # 好きな半角英数字に変更してOKです(例では ID: user, パスワード: vtuber2026)
    app.launch(auth=("v", "0409"))