edost4 edost4 - 4 months ago 30
Python Question

Add a Loop to an existing YouTube API Python script

As confirmed with YouTube Support, unfortunately the way the YouTube API is set up, you can’t pull both Country and Device Type as dimension at the same time, and the only work-around is to pull a Device Type report, and add 1 Country at a time in the filter.
Therefore, you need to fire an API call for each country, which can be accomplished with a proper loop command, iterating the API over every possible country.
I managed to script the code for the API itself, but I need help with the loop over all possible countries (whether its through an API call getting the full country list or simply by referencing a csv file with the country list).
FYI, it is not possible to use device type as filter for a country report.
Can anyone please give me a hand in doing that? Below please find my Python code.

https://1drv.ms/u/s!AlgTM2giFod43mzV1dQARcvsB81o

Answer

Was able to answer my own question, this is the revised code in case anyone is interested: https://1drv.ms/u/s!AlgTM2giFod43m3plTrfSRHOfaCz

#!/usr/bin/python

from datetime import datetime, timedelta
import httplib2
import os
import sys
import csv

from apiclient.discovery import build
from apiclient.errors import HttpError
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
import argparse
from oauth2client.tools import argparser, run_flow


# The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
# the OAuth 2.0 information for this application, including its client_id and
# client_secret. You can acquire an OAuth 2.0 client ID and client secret from
# the Google Developers Console at
# https://console.developers.google.com/.
# Please ensure that you have enabled the YouTube Data and YouTube Analytics
# APIs for your project.
# For more information about using OAuth2 to access the YouTube Data API, see:
#   https://developers.google.com/youtube/v3/guides/authentication
# For more information about the client_secrets.json file format, see:
#   https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
CLIENT_SECRETS_FILE = "client_secretXYZ"

# These OAuth 2.0 access scopes allow for read-only access to the authenticated
# user's account for both YouTube Data API resources and YouTube Analytics Data.
YOUTUBE_SCOPES = ["https://www.googleapis.com/auth/youtube.readonly",
  "https://www.googleapis.com/auth/yt-analytics.readonly"]
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
YOUTUBE_ANALYTICS_API_SERVICE_NAME = "youtubeAnalytics"
YOUTUBE_ANALYTICS_API_VERSION = "v1"

# This variable defines a message to display if the CLIENT_SECRETS_FILE is
# missing.
MISSING_CLIENT_SECRETS_MESSAGE = """
WARNING: Please configure OAuth 2.0

To make this sample run you will need to populate the client_secrets.json file
found at:

   %s

with information from the Developers Console
https://console.developers.google.com/

For more information about the client_secrets.json file format, please visit:
https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),
                                   CLIENT_SECRETS_FILE))


def get_authenticated_services(args):
  flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,
    scope=" ".join(YOUTUBE_SCOPES),
    message=MISSING_CLIENT_SECRETS_MESSAGE)

  storage = Storage("%s-oauth2.json" % sys.argv[0])
  credentials = storage.get()

  if credentials is None or credentials.invalid:
    credentials = run_flow(flow, storage, args)

  http = credentials.authorize(httplib2.Http())

  youtube_analytics = build(YOUTUBE_ANALYTICS_API_SERVICE_NAME,
    YOUTUBE_ANALYTICS_API_VERSION, http=http)

  return youtube_analytics

def run_analytics_report(youtube_analytics, options, count):
  # Call the Analytics API to retrieve a report. For a list of available
  # reports, see:
  # https://developers.google.com/youtube/analytics/v1/channel_reports
  analytics_query_response = youtube_analytics.reports().query(
    ids="channel==%s" % options.channel_id,
    metrics=options.metrics,
    dimensions=options.dimensions,
    filters=options.filters,
    start_date=options.start_date,
    end_date=options.end_date,
    #max_results=options.max_results,
    sort=options.sort
  ).execute()

  print "Analytics Data for Channel %s" % options.channel_id

  if count == 0:
    with open('results.csv', 'w') as csv_out:
           csvWriter=csv.writer(csv_out, delimiter=',', lineterminator = '\n')
           headers = [ch["name"] for ch in analytics_query_response.get("columnHeaders", [])]
           headers.append("country")
           csvWriter.writerow(headers)

  else:
    with open('results.csv', 'a') as csv_out:
      csvWriter=csv.writer(csv_out, delimiter=',', lineterminator = '\n')
      for row in analytics_query_response.get("rows", []):
        values = []
        for value in row:
          values.append(str(value))
        values.append((options.filters[9]+""+options.filters[10]))
        csvWriter.writerow(values)

  print "Results exported to csv"

'''
  for column_header in analytics_query_response.get("columnHeaders", []):
     print "%-20s" % column_header["name"],
  print

  for row in analytics_query_response.get("rows", []):
     for value in row:
       print "%-20s" % value,
     print
'''

if __name__ == "__main__":
  count = 0
  now = datetime.now()
  one_day_ago = (now - timedelta(days=1)).strftime("%Y-%m-%d")
  one_week_ago = (now - timedelta(days=7)).strftime("%Y-%m-%d")
  f = open('countries.csv', 'rb')
  reader = csv.reader(f)

  for row in reader:
    argparser = argparse.ArgumentParser()
    argparser.add_argument("--channel-id", help="Channel ID",
      default="UCJ5v_MCY6GNUBTO8-D3XoAg")
    argparser.add_argument("--metrics", help="Report metrics",
      default="views,estimatedMinutesWatched")
    argparser.add_argument("--dimensions", help="Report dimensions",
      default="deviceType")
    argparser.add_argument("--filters", help="Report filters",
      default="country==" + ''.join(row))
    argparser.add_argument("--start-date", default=one_week_ago,
      help="Start date, in YYYY-MM-DD format")
    argparser.add_argument("--end-date", default=one_day_ago,
      help="End date, in YYYY-MM-DD format")
    #argparser.add_argument("--max-results", help="Max results", default=10)
    argparser.add_argument("--sort", help="Sort order", default="-views")
    args = argparser.parse_args()

    youtube_analytics = get_authenticated_services(args)
    try:
      run_analytics_report(youtube_analytics, args, count)
      count = count + 1
    except HttpError, e:
      print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content)