-
Notifications
You must be signed in to change notification settings - Fork 13
/
youtube.py
180 lines (138 loc) · 6.27 KB
/
youtube.py
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
172
173
174
175
176
177
178
179
180
#!/usr/bin/env papihon3
import os
import requests
import json
from pyyoutube import Api
from utils import display_num, convert_num, download_image
from tweet import twitter_post, twitter_post_image
# Get API key for YouTube
youtube_api_key = os.environ.get('YOUTUBE_API_KEY')
url_video = "https://youtu.be/"
module = "YouTube"
def youtube_data(group):
"""Runs all the YouTube related tasks
It scrapes data from YouTube for the whole group and the single artists
Args:
group: dictionary with the data of the group to scrape
Returns:
the same group dictionary with updated data
"""
print("[{}] Starting tasks...".format(module))
api = Api(api_key=youtube_api_key)
# Getting channel data and stats
channel_data = youtube_get_channel(api, group["youtube"]["url"])
group["youtube"] = youtube_check_channel_change(group["youtube"], channel_data, group["hashtags"])
# Getting video data and stats
videos = youtube_get_videos(api, group["youtube"]["playlist"], group["youtube"]["name"])
group["youtube"]["videos"] = youtube_check_videos_change(group["name"], group["youtube"]["videos"], videos, group["hashtags"])
# Getting Youtube data for each member
for member in group["members"]:
if "youtube" in member:
channel_data = youtube_get_channel(api, member["youtube"]["url"])
member["youtube"] = youtube_check_channel_change(member["youtube"], channel_data, member["hashtags"])
videos = youtube_get_videos(api, member["youtube"]["playlist"], member["youtube"]["name"])
member["youtube"]["videos"] = youtube_check_videos_change(member["name"], member["youtube"]["videos"], videos, member["hashtags"])
print()
return group
def youtube_get_channel(api, channel_id):
"""Gets details about a channel
Args:
- api: The YouTube instance
- channel_id: the ID of that channel on YouTube
Returns:
an dictionary containing all the scraped data of that channel
"""
data = api.get_channel_info(channel_id=channel_id)
channel = data.items[0]
channel_data = {
"name": channel.snippet.title,
"subs": channel.statistics.subscriberCount,
"views": channel.statistics.viewCount,
"playlist": channel.contentDetails.relatedPlaylists.uploads,
"image": channel.snippet.thumbnails.high.url
}
print("[{}] ({}) Fetched channel".format(module, channel_data["name"]))
return channel_data
def youtube_get_videos(api, playlist_id, name):
"""Gets videos from a playlist
Args:
- api: The YouTube instance
- playlist_id: the ID of the playlist on YouTube
- name: name of the channel owner of the playlist
Returns:
a list of videos
"""
videos = []
playlist = api.get_playlist_items(playlist_id=playlist_id, count=None)
for video in playlist.items:
# Try to get the highest quality thumbnail
if video.snippet.thumbnails.maxres is None:
thumbnail = video.snippet.thumbnails.default.url
else:
thumbnail = video.snippet.thumbnails.maxres.url
videos.append(
{"name": video.snippet.title,
"url": video.snippet.resourceId.videoId,
"image": thumbnail}
)
print("[{}] ({}) Fetched {} videos".format(module, name, len(videos)))
return videos
def youtube_check_channel_change(old_channel, new_channel, hashtags):
"""Checks if there is any change in the number of subscribers or total views of the channel
It compares the old channel data with the new (already fetched) data.
Args:
- old_channel: dictionary that contains all the old data of the channel
- new_channel: dictionary that contains all the updated data of the channel
- hashtags: hashtags to add to the Tweet
Returns:
a dictionary with updated data of the channel
"""
# Tweet if subs reach a new 100 thousands
if convert_num("100K", new_channel["subs"]) != convert_num("100K", old_channel["subs"]):
twitter_post_image(
"{} reached {} subscribers on #YouTube\n{}".format(new_channel["name"], display_num(new_channel["subs"], decimal=True), hashtags),
download_image(new_channel["image"]),
display_num(new_channel["subs"], short=True, decimal=True),
text_size=150
)
old_channel["subs"] = new_channel["subs"]
# Tweet if total views increase and reach a new mark (based on the views_scale)
if new_channel["views"] > old_channel["total_views"]:
if convert_num(old_channel["views_scale"], new_channel["views"]) != convert_num(old_channel["views_scale"], old_channel["total_views"]):
twitter_post_image(
"{} reached {} total views on #YouTube\n{}".format(new_channel["name"], display_num(new_channel["views"]), hashtags),
download_image(new_channel["image"]),
display_num(new_channel["views"], short=True)
)
old_channel["total_views"] = new_channel["views"]
old_channel["playlist"] = new_channel["playlist"]
old_channel["name"] = new_channel["name"]
old_channel["image"] = new_channel["image"]
return old_channel
def youtube_check_videos_change(name, old_videos, new_videos, hashtags):
"""Checks if there is any new video
It compares the old videos list of the artist with the new (already fetched) videos list.
It tweets if there is a new release or if a video reaches a new views goal.
Args:
- name: name of the channel
- old_videos: list that contains all the old videos
- new_videos: list that contains all the updated videos
- hashtags: hashtags to append to the Tweet
Returns:
new_videos
"""
if old_videos is not None:
for new_video in new_videos:
found = False
for old_video in old_videos:
if new_video["url"] == old_video["url"]:
found = True
if not found:
twitter_post_image(
"{} uploaded a new #video on #YouTube: {}\n{}\n{}".format(name, new_video["name"], url_video + new_video["url"], hashtags),
download_image(new_video["image"]),
"NEW",
text_size=100,
crop=True
)
return new_videos