Created
July 4, 2019 05:26
-
-
Save prinsss/fbe7fe6a9aa42575122a9144b998ce13 to your computer and use it in GitHub Desktop.
Check whether YouTube channel is live streaming.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
# coding: utf-8 | |
import re | |
import sys | |
import json | |
import requests | |
from retrying import retry | |
headers = { | |
'Accept-Language': 'en-US,en;q=0.8', | |
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:67.0) Gecko/20100101 Firefox/67.0', | |
} | |
# Apply for a YouTube Data API v3 key here | |
# https://console.developers.google.com/apis/library/youtube.googleapis.com | |
api_key = '' | |
@retry(stop_max_attempt_number=3) | |
def get(url: str) -> str: | |
try: | |
r = requests.get(url, headers=headers) | |
return r.text | |
except requests.RequestException: | |
pass | |
def get_json(url: str) -> dict: | |
try: | |
return json.loads(get(url)) | |
except json.decoder.JSONDecodeError: | |
pass | |
def get_video_info(video_id) -> dict: | |
""" | |
Returns dict of video info. | |
YouTube API doc: https://developers.google.com/youtube/v3/docs/videos/list | |
""" | |
try: | |
response = get_json( | |
f'https://www.googleapis.com/youtube/v3/videos?id={video_id}&' | |
f'key={api_key}&part=liveStreamingDetails,snippet' | |
) | |
item = response['items'][0] | |
return item | |
except Exception: | |
pass | |
def get_live_video_info_by_channel_id(channel_id: str) -> dict: | |
""" | |
Get current live video of given channel. | |
Returns dict of video info with keys: | |
{ id, title, description, publishedAt, thumbnails, channelId, channelTitle, liveBroadcastContent, } | |
YouTube API doc: https://developers.google.com/youtube/v3/docs/search/list | |
""" | |
try: | |
response = get_json( | |
f'https://www.googleapis.com/youtube/v3/search?part=snippet&' | |
f'channelId={channel_id}&eventType=live&maxResults=1&type=video&key={api_key}' | |
) | |
video_id = response['items'][0]['id']['videoId'] | |
# The video info in the API response is not complete, | |
# so we request the video info with another API here. | |
video_info = get_video_info(video_id) | |
except Exception: | |
raise | |
return { | |
'id': video_id, | |
**video_info['snippet'] | |
} | |
def get_live_video_info_from_html(html: str) -> dict: | |
""" | |
Extract video info from HTML of channel page. | |
""" | |
# regex = r'{"itemSectionRenderer":{"contents":\[{"shelfRenderer":{"title":{"runs":\[{"text":"Live now".+?"content":{"expandedShelfContentsRenderer":{"items":(.+?),"showMoreText":{"runs":\[{"text":"Show more"}]}}}' | |
regex = r'"contents":\[{"channelFeaturedContentRenderer":{"items":(.+?)}}],"trackingParams"' | |
json_items = json.loads(re.search(regex, html).group(1)) | |
extract = json_items[0]['videoRenderer'] | |
# print(json.dumps(json_items, indent=2, separators=(',', ': '))) | |
# exit(0) | |
if (extract['badges'][0]['metadataBadgeRenderer']['label'] != 'LIVE NOW'): | |
raise RuntimeError('Not live') | |
return { | |
'id': extract['videoId'], | |
'title': extract['title']['simpleText'], | |
'description': extract['descriptionSnippet']['simpleText'] | |
} | |
def check_channel_live_streaming(channel_id: str) -> bool: | |
try: | |
html = get(f'https://www.youtube.com/channel/{channel_id}/featured') | |
if '"label":"LIVE NOW"' in html: | |
# video_info = get_live_video_info_by_channel_id(channel_id) | |
video_info = get_live_video_info_from_html(html) | |
return video_info | |
else: | |
return False | |
except Exception: | |
raise | |
# usage: ./check_youtube.py youtube_channel_id | |
if __name__ == '__main__': | |
if (len(sys.argv) < 2): | |
print('usage: ' + sys.argv[0] + ' youtube_channel_id', file=sys.stderr) | |
exit(1) | |
channel_id = sys.argv[1] | |
info = check_channel_live_streaming(channel_id) | |
if info: | |
# Same output format as | |
# youtube-dl --get-id --get-title --get-description | |
print(info['title']) | |
print(info['id']) | |
print(info['description']) | |
else: | |
print(f'No live streams for channel {channel_id} available now', file=sys.stderr) | |
exit(1) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment