Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit 6fd30ed

Browse filesBrowse files
committed
add youtube api tutorial
1 parent 67b84d8 commit 6fd30ed
Copy full SHA for 6fd30ed

File tree

Expand file treeCollapse file tree

9 files changed

+736
-0
lines changed
Open diff view settings
Filter options
Expand file treeCollapse file tree

9 files changed

+736
-0
lines changed
Open diff view settings
Collapse file

‎README.md‎

Copy file name to clipboardExpand all lines: README.md
+1Lines changed: 1 addition & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,7 @@ This is a repository of all the tutorials of [The Python Code](https://www.thepy
133133
- [How to Get Google Page Ranking in Python](https://www.thepythoncode.com/article/get-google-page-ranking-by-keyword-in-python). ([code](general/getting-google-page-ranking))
134134
- [How to Make a Telegram Bot in Python](https://www.thepythoncode.com/article/make-a-telegram-bot-in-python). ([code](general/telegram-bot))
135135
- [How to Use Gmail API in Python](https://www.thepythoncode.com/article/use-gmail-api-in-python). ([code](general/gmail-api))
136+
- [How to Use YouTube API in Python](https://www.thepythoncode.com/article/using-youtube-api-in-python). ([code](general/youtube-api))
136137

137138
- ### [Database](https://www.thepythoncode.com/topic/using-databases-in-python)
138139
- [How to Use MySQL Database in Python](https://www.thepythoncode.com/article/using-mysql-database-in-python). ([code](database/mysql-connector))
Collapse file

‎general/youtube-api/README.md‎

Copy file name to clipboard
+8Lines changed: 8 additions & 0 deletions
  • Display the source diff
  • Display the rich diff
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
# [How to Use YouTube API in Python](https://www.thepythoncode.com/article/using-youtube-api-in-python)
2+
To run this:
3+
- `pip3 install -r requirements.txt`
4+
- For complete code, use `youtube-api.ipynb`
5+
- To get video details: `video_details.py`
6+
- To get channel details: `channel_details.py`
7+
- To search by keyword: `search_by_keyword.py`
8+
- To extract comments: `comments.py`
Collapse file
+74Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
from utils import (
2+
youtube_authenticate,
3+
get_channel_id_by_url,
4+
get_channel_details,
5+
get_video_details,
6+
print_video_infos
7+
)
8+
9+
10+
def get_channel_videos(youtube, **kwargs):
11+
return youtube.search().list(
12+
**kwargs
13+
).execute()
14+
15+
16+
if __name__ == "__main__":
17+
# authenticate to YouTube API
18+
youtube = youtube_authenticate()
19+
channel_url = "https://www.youtube.com/channel/UC8butISFwT-Wl7EV0hUK0BQ"
20+
# get the channel ID from the URL
21+
channel_id = get_channel_id_by_url(youtube, channel_url)
22+
# get the channel details
23+
response = get_channel_details(youtube, id=channel_id)
24+
# extract channel infos
25+
snippet = response["items"][0]["snippet"]
26+
statistics = response["items"][0]["statistics"]
27+
channel_country = snippet["country"]
28+
channel_description = snippet["description"]
29+
channel_creation_date = snippet["publishedAt"]
30+
channel_title = snippet["title"]
31+
channel_subscriber_count = statistics["subscriberCount"]
32+
channel_video_count = statistics["videoCount"]
33+
channel_view_count = statistics["viewCount"]
34+
print(f"""
35+
Title: {channel_title}
36+
Published At: {channel_creation_date}
37+
Description: {channel_description}
38+
Country: {channel_country}
39+
Number of videos: {channel_video_count}
40+
Number of subscribers: {channel_subscriber_count}
41+
Total views: {channel_view_count}
42+
""")
43+
# the following is grabbing channel videos
44+
# number of pages you want to get
45+
n_pages = 2
46+
# counting number of videos grabbed
47+
n_videos = 0
48+
next_page_token = None
49+
for i in range(n_pages):
50+
params = {
51+
'part': 'snippet',
52+
'q': '',
53+
'channelId': channel_id,
54+
'type': 'video',
55+
}
56+
if next_page_token:
57+
params['pageToken'] = next_page_token
58+
res = get_channel_videos(youtube, **params)
59+
channel_videos = res.get("items")
60+
for video in channel_videos:
61+
n_videos += 1
62+
video_id = video["id"]["videoId"]
63+
# easily construct video URL by its ID
64+
video_url = f"https://www.youtube.com/watch?v={video_id}"
65+
video_response = get_video_details(youtube, id=video_id)
66+
print(f"================Video #{n_videos}================")
67+
# print the video details
68+
print_video_infos(video_response)
69+
print(f"Video URL: {video_url}")
70+
print("="*40)
71+
# if there is a next page, then add it to our parameters
72+
# to proceed to the next page
73+
if "nextPageToken" in res:
74+
next_page_token = res["nextPageToken"]
Collapse file

‎general/youtube-api/comments.py‎

Copy file name to clipboard
+60Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
from utils import youtube_authenticate, get_video_id_by_url, get_channel_id_by_url
2+
3+
4+
def get_comments(youtube, **kwargs):
5+
return youtube.commentThreads().list(
6+
part="snippet",
7+
**kwargs
8+
).execute()
9+
10+
11+
12+
if __name__ == "__main__":
13+
# authenticate to YouTube API
14+
youtube = youtube_authenticate()
15+
# URL can be a channel or a video, to extract comments
16+
url = "https://www.youtube.com/watch?v=jNQXAC9IVRw&ab_channel=jawed"
17+
if "watch" in url:
18+
# that's a video
19+
video_id = get_video_id_by_url(url)
20+
params = {
21+
'videoId': video_id,
22+
'maxResults': 2,
23+
'order': 'relevance', # default is 'time' (newest)
24+
}
25+
else:
26+
# should be a channel
27+
channel_id = get_channel_id_by_url(url)
28+
params = {
29+
'allThreadsRelatedToChannelId': channel_id,
30+
'maxResults': 2,
31+
'order': 'relevance', # default is 'time' (newest)
32+
}
33+
# get the first 2 pages (2 API requests)
34+
n_pages = 2
35+
for i in range(n_pages):
36+
# make API call to get all comments from the channel (including posts & videos)
37+
response = get_comments(youtube, **params)
38+
items = response.get("items")
39+
# if items is empty, breakout of the loop
40+
if not items:
41+
break
42+
for item in items:
43+
comment = item["snippet"]["topLevelComment"]["snippet"]["textDisplay"]
44+
updated_at = item["snippet"]["topLevelComment"]["snippet"]["updatedAt"]
45+
like_count = item["snippet"]["topLevelComment"]["snippet"]["likeCount"]
46+
comment_id = item["snippet"]["topLevelComment"]["id"]
47+
print(f"""\
48+
Comment: {comment}
49+
Likes: {like_count}
50+
Updated At: {updated_at}
51+
==================================\
52+
""")
53+
if "nextPageToken" in response:
54+
# if there is a next page
55+
# add next page token to the params we pass to the function
56+
params["pageToken"] = response["nextPageToken"]
57+
else:
58+
# must be end of comments!!!!
59+
break
60+
print("*"*70)
Collapse file
+3Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
google-api-python-client
2+
google-auth-httplib2
3+
google-auth-oauthlib
Collapse file
+22Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
from utils import (
2+
youtube_authenticate,
3+
get_video_details,
4+
print_video_infos,
5+
search
6+
)
7+
8+
9+
if __name__ == "__main__":
10+
# authenticate to YouTube API
11+
youtube = youtube_authenticate()
12+
# search for the query 'python' and retrieve 2 items only
13+
response = search(youtube, q="python", maxResults=2)
14+
items = response.get("items")
15+
for item in items:
16+
# get the video ID
17+
video_id = item["id"]["videoId"]
18+
# get the video details
19+
video_response = get_video_details(youtube, id=video_id)
20+
# print the video details
21+
print_video_infos(video_response)
22+
print("="*50)
Collapse file

‎general/youtube-api/utils.py‎

Copy file name to clipboard
+154Lines changed: 154 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,154 @@
1+
from googleapiclient.discovery import build
2+
from google_auth_oauthlib.flow import InstalledAppFlow
3+
from google.auth.transport.requests import Request
4+
5+
import urllib.parse as p
6+
import re
7+
import os
8+
import pickle
9+
10+
SCOPES = ["https://www.googleapis.com/auth/youtube.force-ssl"]
11+
12+
def youtube_authenticate():
13+
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
14+
api_service_name = "youtube"
15+
api_version = "v3"
16+
client_secrets_file = "credentials.json"
17+
creds = None
18+
# the file token.pickle stores the user's access and refresh tokens, and is
19+
# created automatically when the authorization flow completes for the first time
20+
if os.path.exists("token.pickle"):
21+
with open("token.pickle", "rb") as token:
22+
creds = pickle.load(token)
23+
# if there are no (valid) credentials availablle, let the user log in.
24+
if not creds or not creds.valid:
25+
if creds and creds.expired and creds.refresh_token:
26+
creds.refresh(Request())
27+
else:
28+
flow = InstalledAppFlow.from_client_secrets_file(client_secrets_file, SCOPES)
29+
creds = flow.run_local_server(port=0)
30+
# save the credentials for the next run
31+
with open("token.pickle", "wb") as token:
32+
pickle.dump(creds, token)
33+
34+
return build(api_service_name, api_version, credentials=creds)
35+
36+
37+
def get_channel_details(youtube, **kwargs):
38+
return youtube.channels().list(
39+
part="statistics,snippet,contentDetails",
40+
**kwargs
41+
).execute()
42+
43+
44+
def search(youtube, **kwargs):
45+
return youtube.search().list(
46+
part="snippet",
47+
**kwargs
48+
).execute()
49+
50+
51+
def get_video_details(youtube, **kwargs):
52+
return youtube.videos().list(
53+
part="snippet,contentDetails,statistics",
54+
**kwargs
55+
).execute()
56+
57+
58+
def print_video_infos(video_response):
59+
items = video_response.get("items")[0]
60+
# get the snippet, statistics & content details from the video response
61+
snippet = items["snippet"]
62+
statistics = items["statistics"]
63+
content_details = items["contentDetails"]
64+
# get infos from the snippet
65+
channel_title = snippet["channelTitle"]
66+
title = snippet["title"]
67+
description = snippet["description"]
68+
publish_time = snippet["publishedAt"]
69+
# get stats infos
70+
comment_count = statistics["commentCount"]
71+
like_count = statistics["likeCount"]
72+
dislike_count = statistics["dislikeCount"]
73+
view_count = statistics["viewCount"]
74+
# get duration from content details
75+
duration = content_details["duration"]
76+
# duration in the form of something like 'PT5H50M15S'
77+
# parsing it to be something like '5:50:15'
78+
parsed_duration = re.search(f"PT(\d+H)?(\d+M)?(\d+S)", duration).groups()
79+
duration_str = ""
80+
for d in parsed_duration:
81+
if d:
82+
duration_str += f"{d[:-1]}:"
83+
duration_str = duration_str.strip(":")
84+
print(f"""
85+
Title: {title}
86+
Description: {description}
87+
Channel Title: {channel_title}
88+
Publish time: {publish_time}
89+
Duration: {duration_str}
90+
Number of comments: {comment_count}
91+
Number of likes: {like_count}
92+
Number of dislikes: {dislike_count}
93+
Number of views: {view_count}
94+
""")
95+
96+
97+
def parse_channel_url(url):
98+
"""
99+
This function takes channel `url` to check whether it includes a
100+
channel ID, user ID or channel name
101+
"""
102+
path = p.urlparse(url).path
103+
id = path.split("/")[-1]
104+
if "/c/" in path:
105+
return "c", id
106+
elif "/channel/" in path:
107+
return "channel", id
108+
elif "/user/" in path:
109+
return "user", id
110+
111+
112+
def get_channel_id_by_url(youtube, url):
113+
"""
114+
Returns channel ID of a given `id` and `method`
115+
- `method` (str): can be 'c', 'channel', 'user'
116+
- `id` (str): if method is 'c', then `id` is display name
117+
if method is 'channel', then it's channel id
118+
if method is 'user', then it's username
119+
"""
120+
# parse the channel URL
121+
method, id = parse_channel_url(url)
122+
if method == "channel":
123+
# if it's a channel ID, then just return it
124+
return id
125+
elif method == "user":
126+
# if it's a user ID, make a request to get the channel ID
127+
response = get_channel_details(youtube, forUsername=id)
128+
items = response.get("items")
129+
if items:
130+
channel_id = items[0].get("id")
131+
return channel_id
132+
elif method == "c":
133+
# if it's a channel name, search for the channel using the name
134+
# may be inaccurate
135+
response = search(youtube, q=id, maxResults=1)
136+
items = response.get("items")
137+
if items:
138+
channel_id = items[0]["snippet"]["channelId"]
139+
return channel_id
140+
raise Exception(f"Cannot find ID:{id} with {method} method")
141+
142+
143+
def get_video_id_by_url(url):
144+
"""
145+
Return the Video ID from the video `url`
146+
"""
147+
# split URL parts
148+
parsed_url = p.urlparse(url)
149+
# get the video ID by parsing the query of the URL
150+
video_id = p.parse_qs(parsed_url.query).get("v")
151+
if video_id:
152+
return video_id[0]
153+
else:
154+
raise Exception(f"Wasn't able to parse video URL: {url}")
Collapse file
+18Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
from utils import (
2+
youtube_authenticate,
3+
get_video_id_by_url,
4+
get_video_details,
5+
print_video_infos
6+
)
7+
8+
9+
if __name__ == "__main__":
10+
# authenticate to YouTube API
11+
youtube = youtube_authenticate()
12+
video_url = "https://www.youtube.com/watch?v=jNQXAC9IVRw&ab_channel=jawed"
13+
# parse video ID from URL
14+
video_id = get_video_id_by_url(video_url)
15+
# make API call to get video info
16+
response = get_video_details(youtube, id=video_id)
17+
# print extracted video infos
18+
print_video_infos(response)

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.