HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Youtube playlist saver with Google API

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
googlewithyoutubeplaylistsaverapi

Problem

I have a problem with Youtube videos being deleted from my big playlist and not knowing which videos got removed. So, I decided to write a Python script to save certain information(title etc.) about the videos in a playlist into a text-file. I particularly don't like the setChannelNames() func, but that's the best I could write it.

```
import os
import argparse
import codecs
import datetime
import sys
from apiclient.discovery import build

DEVELOPER_KEY = "REPLACE_THIS_WITH_YOUR_OWN_API_KEY"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
RESULTS_PER_PAGE = 50 #1-50 as per Google's rules.
MAX_PLAYLIST_SIZE = 5000

def getArgs():
"""
Process command-line arguments.
"""
parser = argparse.ArgumentParser(description='Retrieve a list of youtube videos in a playlist.')
parser.add_argument("id", type=str, metavar="id", help="Youtube ID of the playlist to scrap.")
parser.add_argument('-dt', '--date', action='store_true', help="Include the date when the video was added to the playlist?")
parser.add_argument('-ds', '--description', action='store_true', help="Include the description of videos?")
parser.add_argument('-un', '--uploadername', action='store_true', help="Include the channel name of the uploader of video?")

args = parser.parse_args()
args = vars(args) #Turn into dict-like view.
return args

def getExtraFields(args):
"""
Returns a string of what information to filter in the Google API based on args optional parameters.
"""
extraFields = ""

if args["description"]:
extraFields += ",description"

if args["date"]:
extraFields += ",publishedAt"

if args["uploadername"]:
extraFields += ",resourceId(videoId)"

return extraFields

def getExtraInfo(args, item):
"""
Returns a string of information to save with the video name based on args optional parameters.
"""
extraInfo = ""

if args["uploadername"]:
extraInfo += " |Uploader: {}|

Solution

Ok, I'll give it a try but please bear with my answer as I don't have an API key to test this.

I'll start as I always do with some style guides which you can read about on the official page: PEP8

1.Comments

When writing inline comments, you should have two spaces after the last character, and one space after # (e.g. test_comment_string = 'some text' # this is a test string comment

2.Spacing and formatting

Between methods you should have two spaces, not just one:

def getArgs():
    ...

def getExtraFields(args)
    ...


Try to limit all lines to max. 120 characters. The official documentation says the maximum length shouldn't be greater than 79. But I just like the Intelij (Pycharm) proposed style better (I guess here is a mater of preference but anyhow.. it helps readability)

Instead of i = i + 1 you can use an augmented assignment: i += 1. I saw you used some of these assignments. Try to be consistent when writing code!

3.Naming conventions

It's also specified in PEP8 the following (about variables / methods naming):


Use the function naming rules: lowercase with words separated by
underscores as necessary to improve readability.

That said, extraFields would become extra_fields

I've seen many people using also camelCase naming conventions for variables so as long as you're being consistent with your code it's ok.

The same rule applies for your methods:

getArgs() -> get_args()

4.Imports

Don't import modules if you're not using them. It's confusing. For example, the os module is not used anywhere, so why would you import it ?

Doing all the above modifications, we now have the following:

```
import argparse
import codecs
import datetime
import sys

from apiclient.discovery import build

DEVELOPER_KEY = "REPLACE_THIS_WITH_YOUR_OWN_API_KEY"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
RESULTS_PER_PAGE = 50 # 1-50 as per Google's rules.
MAX_PLAYLIST_SIZE = 5000

def get_args():
"""
Process command-line arguments.
"""
parser = argparse.ArgumentParser(description='Retrieve a list of youtube videos in a playlist.')
parser.add_argument("id", type=str, metavar="id", help="Youtube ID of the playlist to scrap.")
parser.add_argument('-dt', '--date', action='store_true',
help="Include the date when the video was added to the playlist?")
parser.add_argument('-ds', '--description', action='store_true', help="Include the description of videos?")
parser.add_argument('-un', '--uploadername', action='store_true',
help="Include the channel name of the uploader of video?")

args = parser.parse_args()
args = vars(args) # Turn into dict-like view.
return args

def get_extra_fields(args):
"""
Returns a string of what information to filter in the Google API based on args optional parameters.
"""
extra_fields = ""

if args["description"]:
extra_fields += ",description"

if args["date"]:
extra_fields += ",publishedAt"

if args["uploadername"]:
extra_fields += ",resourceId(videoId)"

return extra_fields

def get_extra_info(args, item):
"""
Returns a string of information to save with the video name based on args optional parameters.
"""
extra_info = ""

if args["uploadername"]:
extra_info += " |Uploader: {}|".format(item["snippet"]["resourceId"]["uploader"])

if args["date"]:
extra_info += " |Date Added: {}|".format(item["snippet"]["publishedAt"][:-5]) # -5 to remove 000Z

if args["description"]:
extra_info += " |Description: {}|".format(item["snippet"]["description"])

return extra_info

def save(pages, file_name, args):
"""
Saves selected playlistItems' information in a txt.
"""
f = codecs.open(file_name, "wb", "utf-8")

i = 0
for playlist_items in pages:
for items in playlist_items["items"]:
i += 1
f.write("{}.".format(i) + str(items["snippet"]["title"]) + get_extra_info(args, items) + u'\r\n')

f.close()

def set_channel_names(pages):
"""
Retrieves all the videos in pages and gets the uploader's name.
Sets the uploader's name to the playlistItem's ["snippet"]["resourceId"]["uploader"].
"""
# videoIds = [item["snippet"]["resourceId"]["videoId"] for playlistItem in pages for item in playlistItem["items"]]
video_ids = []
for playlist_items in pages:
for items in playlist_items["items"]:
video_ids.append(items["snippet"]["resourceId"]["videoId"])

for i in range(1, playlist_items["pageInfo"]["totalResults"]):
video_ids_string = ""
if i % RESULTS_PER_PAGE == 0 or i == playlist_items["pageInfo"]["totalResults"] - 1:
for id in video_ids[:RESULTS_PER_PAGE]: # Generate the string of ids to put into the API request.
video_ids_string += "{},".format(id)

video_ids_string = video_ids_string[:-1] # Remov

Code Snippets

def getArgs():
    ...


def getExtraFields(args)
    ...
import argparse
import codecs
import datetime
import sys

from apiclient.discovery import build

DEVELOPER_KEY = "REPLACE_THIS_WITH_YOUR_OWN_API_KEY"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
RESULTS_PER_PAGE = 50  # 1-50 as per Google's rules.
MAX_PLAYLIST_SIZE = 5000


def get_args():
    """
    Process command-line arguments.
    """
    parser = argparse.ArgumentParser(description='Retrieve a list of youtube videos in a playlist.')
    parser.add_argument("id", type=str, metavar="id", help="Youtube ID of the playlist to scrap.")
    parser.add_argument('-dt', '--date', action='store_true',
                        help="Include the date when the video was added to the playlist?")
    parser.add_argument('-ds', '--description', action='store_true', help="Include the description of videos?")
    parser.add_argument('-un', '--uploadername', action='store_true',
                        help="Include the channel name of the uploader of video?")

    args = parser.parse_args()
    args = vars(args)  # Turn into dict-like view.
    return args


def get_extra_fields(args):
    """
    Returns a string of what information to filter in the Google API based on args optional parameters.
    """
    extra_fields = ""

    if args["description"]:
        extra_fields += ",description"

    if args["date"]:
        extra_fields += ",publishedAt"

    if args["uploadername"]:
        extra_fields += ",resourceId(videoId)"

    return extra_fields


def get_extra_info(args, item):
    """
    Returns a string of information to save with the video name based on args optional parameters.
    """
    extra_info = ""

    if args["uploadername"]:
        extra_info += " |Uploader: {}|".format(item["snippet"]["resourceId"]["uploader"])

    if args["date"]:
        extra_info += " |Date Added: {}|".format(item["snippet"]["publishedAt"][:-5])  # -5 to remove 000Z

    if args["description"]:
        extra_info += " |Description: {}|".format(item["snippet"]["description"])

    return extra_info


def save(pages, file_name, args):
    """
    Saves selected playlistItems' information in a txt.
    """
    f = codecs.open(file_name, "wb", "utf-8")

    i = 0
    for playlist_items in pages:
        for items in playlist_items["items"]:
            i += 1
            f.write("{}.".format(i) + str(items["snippet"]["title"]) + get_extra_info(args, items) + u'\r\n')

    f.close()


def set_channel_names(pages):
    """
    Retrieves all the videos in pages and gets the uploader's name.
    Sets the uploader's name to the playlistItem's ["snippet"]["resourceId"]["uploader"].
    """
    # videoIds = [item["snippet"]["resourceId"]["videoId"] for playlistItem in pages for item in playlistItem["items"]]
    video_ids = []
    for playlist_items in pages:
        for items in playlist_items["items"]:
            video_ids.append(items["snippet"]["resourceId"]["videoId"])

    for i in range(1, playlist_items["pageInfo"]["totalResults"]):
        video_
f.write("{}.".format(i) + str(items["snippet"]["title"]) + get_extra_info(args, items) + u'\r\n')
if "nextPageToken" in playlistItems:
   nextPageToken = playlistItems["nextPageToken"]
else:
   break
if not "nextPageToken" in playlistItems:
   break
nextPageToken = playlistItems["nextPageToken"]

Context

StackExchange Code Review Q#132241, answer score: 3

Revisions (0)

No revisions yet.