Upload 2 files
Browse files- app.py +116 -0
- requirements.txt +2 -0
app.py
ADDED
@@ -0,0 +1,116 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import streamlit as st
|
2 |
+
import requests
|
3 |
+
import re
|
4 |
+
|
5 |
+
# Streamlit μ λͺ© λ° μ€λͺ
|
6 |
+
st.title("VOD μ±ν
ν¬λ‘€λ¬")
|
7 |
+
st.write("VOD URLμ μ
λ ₯νκ³ μ±ν
λ°μ΄ν°λ₯Ό ν¬λ‘€λ§ν©λλ€.")
|
8 |
+
|
9 |
+
# URL μ
λ ₯ λ°κΈ°
|
10 |
+
vod_url = st.text_input("VOD URL μ
λ ₯")
|
11 |
+
|
12 |
+
|
13 |
+
# μ±ν
ν¬λ‘€λ§ ν¨μ
|
14 |
+
def crawl_chats(vod_url):
|
15 |
+
# URL μ€μ
|
16 |
+
url = vod_url + "/chats"
|
17 |
+
|
18 |
+
# μμ² ν€λ (νμμ μΏ ν€λ κΈ°ν ν€λ μ 보 μΆκ°)
|
19 |
+
headers = {
|
20 |
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
|
21 |
+
"Accept": "application/json, text/plain, */*",
|
22 |
+
"Referer": "https://chzzk.naver.com/video/3646597",
|
23 |
+
"Origin": "https://chzzk.naver.com",
|
24 |
+
"Cookie": "your-cookie-string-here" # λ‘κ·ΈμΈ ν κ°λ°μ λꡬμ Request Headers νμμ μΏ ν€ κ° λ³΅μ¬
|
25 |
+
}
|
26 |
+
|
27 |
+
# μ΄κΈ° μμ² νλΌλ―Έν° μ€μ
|
28 |
+
params = {
|
29 |
+
"playerMessageTime": 0, # μμ μμ (0 = 0μ΄)
|
30 |
+
"previousVideoChatSize": 50 # κ°μ Έμ¬ μ±ν
λ©μμ§ μ
|
31 |
+
}
|
32 |
+
|
33 |
+
# λ§μ§λ§ μμ§ν μ±ν
λ©μμ§ μ μ₯ λ³μ
|
34 |
+
last_collected_chats = None
|
35 |
+
total_collected_chats = 0
|
36 |
+
chat_logs = []
|
37 |
+
|
38 |
+
# μ±ν
λ°μ΄ν°λ₯Ό μμ°¨μ μΌλ‘ μμ²νμ¬ κ°μ Έμ€κΈ°
|
39 |
+
while True:
|
40 |
+
# API μμ² λ³΄λ΄κΈ°
|
41 |
+
response = requests.get(url, params=params, headers=headers)
|
42 |
+
|
43 |
+
# μμ² κ²°κ³Όκ° μ±κ³΅μ μ΄μ§ μμ κ²½μ° μ’
λ£
|
44 |
+
if response.status_code != 200:
|
45 |
+
return f"API μμ² μ€ν¨: {response.status_code}"
|
46 |
+
|
47 |
+
# JSON λ°μ΄ν°λ‘ λ³ν
|
48 |
+
data = response.json()
|
49 |
+
|
50 |
+
# μ±ν
λ©μμ§κ° ν¬ν¨λ 'videoChats' λ°°μ΄ κ°μ Έμ€κΈ°
|
51 |
+
chats = data.get("content", {}).get("videoChats", [])
|
52 |
+
|
53 |
+
# μ±ν
λ©μμ§κ° μλ€λ©΄ μ’
λ£
|
54 |
+
if not chats:
|
55 |
+
break
|
56 |
+
|
57 |
+
# νμ¬ μμ§λ μ±ν
μ΄ μ΄μ μ μμ§λ μ±ν
κ³Ό λμΌνμ§ νμΈ
|
58 |
+
if last_collected_chats == chats:
|
59 |
+
break
|
60 |
+
|
61 |
+
# μ±ν
λ©μμ§(content)μ playerMessageTime(μ±ν
μκ°)λ§ μμ§
|
62 |
+
for chat in chats:
|
63 |
+
chat_content = chat.get("content") # μ±ν
λ©μμ§ λ΄μ©
|
64 |
+
message_time = chat.get("playerMessageTime") # μ±ν
λ©μμ§ μ
λ ₯ μκ°
|
65 |
+
|
66 |
+
# μμ ν
μ€νΈλ§ ν¬ν¨λ μ±ν
λ©μμ§ νν°λ§
|
67 |
+
if not re.search(r'{:[^}]*:}', chat_content): # μ΄λͺ¨ν°μ½ νμμ λ©μμ§κ° μμ λλ§ μμ§
|
68 |
+
# λ°λ¦¬μ΄ μκ°μ "μκ°:λΆ:μ΄" νμμΌλ‘ λ³ν
|
69 |
+
hours, remainder = divmod(message_time // 1000, 3600)
|
70 |
+
minutes, seconds = divmod(remainder, 60)
|
71 |
+
|
72 |
+
if hours > 0:
|
73 |
+
formatted_time = f"{hours:02}:{minutes:02}:{seconds:02}" # "HH:MM:SS" νμ
|
74 |
+
else:
|
75 |
+
formatted_time = f"{minutes:02}:{seconds:02}" # "MM:SS" νμ
|
76 |
+
|
77 |
+
# μ±ν
λ‘κ·Έμ μΆκ°
|
78 |
+
chat_logs.append(f"{formatted_time} - {chat_content}")
|
79 |
+
|
80 |
+
# λ§μ§λ§μΌλ‘ μμ§ν μ±ν
λ©μμ§ μ
λ°μ΄νΈ
|
81 |
+
last_collected_chats = chats
|
82 |
+
|
83 |
+
# μ±ν
λ°μ΄ν° κ°μ μ
λ°μ΄νΈ λ° μΆλ ₯
|
84 |
+
total_collected_chats += len(chats)
|
85 |
+
|
86 |
+
# λ€μ μμ²μ μν΄ playerMessageTime νλΌλ―Έν° μ
λ°μ΄νΈ
|
87 |
+
next_time = data["content"].get("nextPlayerMessageTime")
|
88 |
+
if next_time is None:
|
89 |
+
break
|
90 |
+
params["playerMessageTime"] = next_time
|
91 |
+
|
92 |
+
# κ²°κ³Ό λ°ν
|
93 |
+
return "\n".join(chat_logs)
|
94 |
+
|
95 |
+
|
96 |
+
# λ²νΌμ λλ μ λ μ±ν
ν¬λ‘€λ§ μμ
|
97 |
+
if st.button("ν¬λ‘€λ§ μμ"):
|
98 |
+
if vod_url:
|
99 |
+
chat_logs = crawl_chats(vod_url)
|
100 |
+
st.text_area("μ±ν
λ‘κ·Έ", value=chat_logs, height=400)
|
101 |
+
|
102 |
+
# νμΌλ‘ μ μ₯
|
103 |
+
file_name = "chat_logs.txt"
|
104 |
+
with open(file_name, "w") as file:
|
105 |
+
file.write(chat_logs)
|
106 |
+
|
107 |
+
# λ€μ΄λ‘λ λ²νΌ νμ
|
108 |
+
with open(file_name, "rb") as file:
|
109 |
+
btn = st.download_button(
|
110 |
+
label="μ±ν
λ‘κ·Έ λ€μ΄λ‘λ",
|
111 |
+
data=file,
|
112 |
+
file_name=file_name,
|
113 |
+
mime="text/plain"
|
114 |
+
)
|
115 |
+
else:
|
116 |
+
st.warning("URLμ μ
λ ₯νμΈμ.")
|
requirements.txt
ADDED
@@ -0,0 +1,2 @@
|
|
|
|
|
|
|
1 |
+
streamlit
|
2 |
+
requests
|