Upload 4 files
Browse files- README.md +1 -12
- app.py +142 -0
- requirements.txt +1 -0
- scheme.json +4 -0
README.md
CHANGED
@@ -1,12 +1 @@
|
|
1 |
-
|
2 |
-
title: SMA
|
3 |
-
emoji: π
|
4 |
-
colorFrom: purple
|
5 |
-
colorTo: pink
|
6 |
-
sdk: streamlit
|
7 |
-
sdk_version: 1.34.0
|
8 |
-
app_file: app.py
|
9 |
-
pinned: false
|
10 |
-
---
|
11 |
-
|
12 |
-
Check out the configuration reference at https://huggingface.co/docs/hub/spaces-config-reference
|
|
|
1 |
+
# AlexMaklay
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
app.py
ADDED
@@ -0,0 +1,142 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
import pandas as pd
|
4 |
+
import streamlit as st
|
5 |
+
from googleapiclient.discovery import build
|
6 |
+
|
7 |
+
|
8 |
+
|
9 |
+
class YouTube:
|
10 |
+
def __init__(self, api_key, channel_id):
|
11 |
+
self.api_key = api_key
|
12 |
+
self.channel_id = channel_id
|
13 |
+
self.youtube = build("youtube", "v3", developerKey=api_key)
|
14 |
+
|
15 |
+
def get_general_channel_info(self):
|
16 |
+
try:
|
17 |
+
request = self.youtube.channels().list(
|
18 |
+
part="snippet,statistics", id=self.channel_id
|
19 |
+
)
|
20 |
+
response = request.execute()
|
21 |
+
channel_info = response["items"][0]
|
22 |
+
|
23 |
+
channel_stats = {
|
24 |
+
"subscribers": channel_info["statistics"]["subscriberCount"],
|
25 |
+
"views": channel_info["statistics"]["viewCount"],
|
26 |
+
"total_videos": channel_info["statistics"]["videoCount"],
|
27 |
+
"title": channel_info["snippet"]["title"],
|
28 |
+
"description": channel_info["snippet"]["description"],
|
29 |
+
"cover": channel_info["snippet"]["thumbnails"]["high"]["url"],
|
30 |
+
"url": f"https://www.youtube.com/channel/{self.channel_id}",
|
31 |
+
}
|
32 |
+
return pd.DataFrame(channel_stats, index=[0])
|
33 |
+
|
34 |
+
except Exception as e:
|
35 |
+
st.error(f"An error occurred: {e}")
|
36 |
+
return pd.DataFrame()
|
37 |
+
|
38 |
+
def get_video_data(self):
|
39 |
+
try:
|
40 |
+
# Get the playlist ID of the channel's uploaded videos.
|
41 |
+
channel_response = (
|
42 |
+
self.youtube.channels()
|
43 |
+
.list(part="contentDetails", id=self.channel_id)
|
44 |
+
.execute()
|
45 |
+
)
|
46 |
+
|
47 |
+
playlist_id = channel_response["items"][0]["contentDetails"][
|
48 |
+
"relatedPlaylists"
|
49 |
+
]["uploads"]
|
50 |
+
|
51 |
+
# Get all videos in the uploads playlist.
|
52 |
+
videos = []
|
53 |
+
next_page_token = None
|
54 |
+
|
55 |
+
while True:
|
56 |
+
playlist_items_response = (
|
57 |
+
self.youtube.playlistItems()
|
58 |
+
.list(
|
59 |
+
part="snippet",
|
60 |
+
maxResults=50, # Maximum is 50 per request
|
61 |
+
playlistId=playlist_id,
|
62 |
+
pageToken=next_page_token,
|
63 |
+
)
|
64 |
+
.execute()
|
65 |
+
)
|
66 |
+
videos.extend(playlist_items_response["items"])
|
67 |
+
next_page_token = playlist_items_response.get("nextPageToken")
|
68 |
+
if next_page_token is None:
|
69 |
+
break
|
70 |
+
|
71 |
+
# Extracting relevant data from each video.
|
72 |
+
video_data = []
|
73 |
+
for video in videos:
|
74 |
+
video_id = video["snippet"]["resourceId"]["videoId"]
|
75 |
+
video_details = (
|
76 |
+
self.youtube.videos()
|
77 |
+
.list(part="statistics,snippet", id=video_id)
|
78 |
+
.execute()
|
79 |
+
)
|
80 |
+
|
81 |
+
if video_details["items"]:
|
82 |
+
video_info = video_details["items"][0]
|
83 |
+
snippet = video_info["snippet"]
|
84 |
+
statistics = video_info["statistics"]
|
85 |
+
|
86 |
+
video_data.append(
|
87 |
+
{
|
88 |
+
"thumbnail": snippet["thumbnails"]["high"]["url"],
|
89 |
+
"publishedAt": snippet["publishedAt"],
|
90 |
+
"url": f"https://www.youtube.com/watch?v={video_id}",
|
91 |
+
"title": snippet["title"],
|
92 |
+
"viewCount": statistics.get("viewCount", 0),
|
93 |
+
"likeCount": statistics.get("likeCount", 0),
|
94 |
+
"commentCount": statistics.get("commentCount", 0),
|
95 |
+
}
|
96 |
+
)
|
97 |
+
|
98 |
+
# Convert to DataFrame
|
99 |
+
df = pd.DataFrame(video_data)
|
100 |
+
return df
|
101 |
+
except Exception as e:
|
102 |
+
st.error(f"An error occurred: {e}")
|
103 |
+
return pd.DataFrame()
|
104 |
+
|
105 |
+
|
106 |
+
api_key = os.environ.get("API_KEY")
|
107 |
+
|
108 |
+
|
109 |
+
with open("scheme.json") as f:
|
110 |
+
scheme = json.load(f)
|
111 |
+
|
112 |
+
st.set_page_config(page_title="Social Media Analytics", page_icon="π§", layout="wide")
|
113 |
+
|
114 |
+
if __name__ == "__main__":
|
115 |
+
selected_category = st.selectbox("Select Channel", scheme.keys())
|
116 |
+
platform = st.selectbox("Select Platform", scheme[selected_category].keys())
|
117 |
+
chanell_id = scheme[selected_category][platform]
|
118 |
+
if st.button("Run"):
|
119 |
+
if platform == "youtube":
|
120 |
+
youtube_account = YouTube(api_key, chanell_id)
|
121 |
+
|
122 |
+
with st.status("Fetching general channel info...", expanded=True) as status:
|
123 |
+
statistics = youtube_account.get_general_channel_info()
|
124 |
+
with st.status("Fetching video data...", expanded=True) as status:
|
125 |
+
video_data = youtube_account.get_video_data()
|
126 |
+
st.balloons()
|
127 |
+
if not statistics.empty:
|
128 |
+
st.image(statistics["cover"][0], width=200)
|
129 |
+
st.write(f"[Channel URL]({statistics['url'][0]})")
|
130 |
+
st.write(
|
131 |
+
statistics[["title", "subscribers", "views", "total_videos"]],
|
132 |
+
unsafe_allow_html=True,
|
133 |
+
)
|
134 |
+
|
135 |
+
video_data["url"] = video_data["url"].apply(
|
136 |
+
lambda x: f'<a href="{x}" target="_blank">{x}</a>'
|
137 |
+
)
|
138 |
+
video_data['thumbnail'] = video_data['thumbnail'].apply(lambda x: f'<img src="{x}" width="200">')
|
139 |
+
st.write(
|
140 |
+
video_data.to_html(escape=False, index=False), unsafe_allow_html=True
|
141 |
+
)
|
142 |
+
|
requirements.txt
ADDED
@@ -0,0 +1 @@
|
|
|
|
|
1 |
+
google-api-python-client
|
scheme.json
ADDED
@@ -0,0 +1,4 @@
|
|
|
|
|
|
|
|
|
|
|
1 |
+
{
|
2 |
+
"BossHorn": { "youtube": "UC_YahReYmOs8397X86TZg2Q" },
|
3 |
+
"manTalksHealth": { "youtube": "UCAvN9D0z_8SQpbFIQftYBPw" }
|
4 |
+
}
|