|
1 | 1 | #!/usr/bin/python
|
2 | 2 |
|
3 |
| -# Usage example: |
4 |
| -# python retrieve_reports.py |
5 |
| - |
6 |
| -import httplib2 |
| 3 | +### |
| 4 | +# |
| 5 | +# This script retrieves YouTube Reporting API reports. Use cases: |
| 6 | +# 1. If you specify a report URL, the script downloads that report. |
| 7 | +# 2. Otherwise, if you specify a job ID, the script retrieves a list of |
| 8 | +# available reports for that job and prompts you to select a report. |
| 9 | +# Then it retrieves that report as in case 1. |
| 10 | +# 3. Otherwise, the list retrieves a list of jobs for the user or, |
| 11 | +# if specified, the content owner that the user is acting on behalf of. |
| 12 | +# Then it prompts the user to select a job, and then executes case 2 and |
| 13 | +# then case 1. |
| 14 | +# Usage examples: |
| 15 | +# python retrieve_reports.py --content_owner_id=<CONTENT_OWNER_ID> --local_file=<LOCAL_FILE> |
| 16 | +# python retrieve_reports.py --content_owner_id=<CONTENT_OWNER_ID> --job_id=<JOB_ID> --local_file=<LOCAL_FILE> |
| 17 | +# python retrieve_reports.py --content_owner_id=<CONTENT_OWNER_ID> --report_url=<REPORT_URL> --local_file=<LOCAL_FILE> |
| 18 | +# |
| 19 | +### |
| 20 | + |
| 21 | +import argparse |
7 | 22 | import os
|
8 |
| -import sys |
9 | 23 |
|
10 |
| -from apiclient.discovery import build |
11 |
| -from apiclient.errors import HttpError |
12 |
| -from apiclient.http import MediaIoBaseDownload |
| 24 | +import google.oauth2.credentials |
| 25 | +import google_auth_oauthlib.flow |
| 26 | +from googleapiclient.discovery import build |
| 27 | +from googleapiclient.errors import HttpError |
| 28 | +from googleapiclient.http import MediaIoBaseDownload |
| 29 | +from google_auth_oauthlib.flow import InstalledAppFlow |
13 | 30 | from io import FileIO
|
14 |
| -from oauth2client.client import flow_from_clientsecrets |
15 |
| -from oauth2client.file import Storage |
16 |
| -from oauth2client.tools import argparser, run_flow |
17 | 31 |
|
18 | 32 |
|
19 | 33 | # The CLIENT_SECRETS_FILE variable specifies the name of a file that contains
|
20 |
| - |
21 | 34 | # the OAuth 2.0 information for this application, including its client_id and
|
22 | 35 | # client_secret. You can acquire an OAuth 2.0 client ID and client secret from
|
23 | 36 | # the {{ Google Cloud Console }} at
|
|
27 | 40 | # https://developers.google.com/youtube/v3/guides/authentication
|
28 | 41 | # For more information about the client_secrets.json file format, see:
|
29 | 42 | # https://developers.google.com/api-client-library/python/guide/aaa_client_secrets
|
30 |
| -CLIENT_SECRETS_FILE = "client_secrets.json" |
31 |
| - |
32 |
| -# This OAuth 2.0 access scope allows for read access to the YouTube Analytics monetary reports for |
33 |
| -# authenticated user's account. Any request that retrieves earnings or ad performance metrics must |
34 |
| -# use this scope. |
35 |
| -YOUTUBE_ANALYTICS_MONETARY_READ_SCOPE = ( |
36 |
| - "https://www.googleapis.com/auth/yt-analytics-monetary.readonly") |
37 |
| -YOUTUBE_REPORTING_API_SERVICE_NAME = "youtubereporting" |
38 |
| -YOUTUBE_REPORTING_API_VERSION = "v1" |
39 |
| - |
40 |
| -# This variable defines a message to display if the CLIENT_SECRETS_FILE is |
41 |
| -# missing. |
42 |
| -MISSING_CLIENT_SECRETS_MESSAGE = """ |
43 |
| -WARNING: Please configure OAuth 2.0 |
44 |
| -
|
45 |
| -To make this sample run you will need to populate the client_secrets.json file |
46 |
| -found at: |
47 |
| - %s |
48 |
| -with information from the APIs Console |
49 |
| -https://console.developers.google.com |
50 |
| -
|
51 |
| -For more information about the client_secrets.json file format, please visit: |
52 |
| -https://developers.google.com/api-client-library/python/guide/aaa_client_secrets |
53 |
| -""" % os.path.abspath(os.path.join(os.path.dirname(__file__), |
54 |
| - CLIENT_SECRETS_FILE)) |
55 |
| - |
56 |
| -# Authorize the request and store authorization credentials. |
57 |
| -def get_authenticated_service(args): |
58 |
| - flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE, scope=YOUTUBE_ANALYTICS_MONETARY_READ_SCOPE, |
59 |
| - message=MISSING_CLIENT_SECRETS_MESSAGE) |
| 43 | +CLIENT_SECRETS_FILE = 'client_secret.json' |
60 | 44 |
|
61 |
| - storage = Storage("%s-oauth2.json" % sys.argv[0]) |
62 |
| - credentials = storage.get() |
63 |
| - |
64 |
| - if credentials is None or credentials.invalid: |
65 |
| - credentials = run_flow(flow, storage, args) |
66 |
| - |
67 |
| - return build(YOUTUBE_REPORTING_API_SERVICE_NAME, YOUTUBE_REPORTING_API_VERSION, |
68 |
| - http=credentials.authorize(httplib2.Http())) |
| 45 | +# This OAuth 2.0 access scope allows for read access to YouTube Analytics |
| 46 | +# monetary reports for the authenticated user's account. Any request that |
| 47 | +# retrieves earnings or ad performance metrics must use this scope. |
| 48 | +SCOPES = ['https://www.googleapis.com/auth/yt-analytics-monetary.readonly'] |
| 49 | +API_SERVICE_NAME = 'youtubereporting' |
| 50 | +API_VERSION = 'v1' |
69 | 51 |
|
| 52 | +# Authorize the request and store authorization credentials. |
| 53 | +def get_authenticated_service(): |
| 54 | + flow = InstalledAppFlow.from_client_secrets_file(CLIENT_SECRETS_FILE, SCOPES) |
| 55 | + credentials = flow.run_console() |
| 56 | + return build(API_SERVICE_NAME, API_VERSION, credentials = credentials) |
| 57 | + |
| 58 | +# Remove keyword arguments that are not set. |
| 59 | +def remove_empty_kwargs(**kwargs): |
| 60 | + good_kwargs = {} |
| 61 | + if kwargs is not None: |
| 62 | + for key, value in kwargs.iteritems(): |
| 63 | + if value: |
| 64 | + good_kwargs[key] = value |
| 65 | + return good_kwargs |
70 | 66 |
|
71 | 67 | # Call the YouTube Reporting API's jobs.list method to retrieve reporting jobs.
|
72 |
| -def list_reporting_jobs(youtube_reporting): |
73 |
| - results = youtube_reporting.jobs().list( |
74 |
| - ).execute() |
| 68 | +def list_reporting_jobs(youtube_reporting, **kwargs): |
| 69 | + # Only include the onBehalfOfContentOwner keyword argument if the user |
| 70 | + # set a value for the --content_owner argument. |
| 71 | + kwargs = remove_empty_kwargs(**kwargs) |
| 72 | + |
| 73 | + # Retrieve the reporting jobs for the user (or content owner). |
| 74 | + results = youtube_reporting.jobs().list(**kwargs).execute() |
75 | 75 |
|
76 |
| - if "jobs" in results and results["jobs"]: |
77 |
| - jobs = results["jobs"] |
| 76 | + if 'jobs' in results and results['jobs']: |
| 77 | + jobs = results['jobs'] |
78 | 78 | for job in jobs:
|
79 |
| - print ("Reporting job id: %s\n name: %s\n for reporting type: %s\n" |
80 |
| - % (job["id"], job["name"], job["reportTypeId"])) |
| 79 | + print ('Reporting job id: %s\n name: %s\n for reporting type: %s\n' |
| 80 | + % (job['id'], job['name'], job['reportTypeId'])) |
81 | 81 | else:
|
82 |
| - print "No jobs found" |
| 82 | + print 'No jobs found' |
83 | 83 | return False
|
84 | 84 |
|
85 | 85 | return True
|
86 | 86 |
|
87 |
| - |
88 | 87 | # Call the YouTube Reporting API's reports.list method to retrieve reports created by a job.
|
89 |
| -def retrieve_reports(youtube_reporting, job_id): |
| 88 | +def retrieve_reports(youtube_reporting, **kwargs): |
| 89 | + # Only include the onBehalfOfContentOwner keyword argument if the user |
| 90 | + # set a value for the --content_owner argument. |
| 91 | + kwargs = remove_empty_kwargs(**kwargs) |
| 92 | + |
| 93 | + # Retrieve available reports for the selected job. |
90 | 94 | results = youtube_reporting.jobs().reports().list(
|
91 |
| - jobId=job_id |
| 95 | + **kwargs |
92 | 96 | ).execute()
|
93 | 97 |
|
94 |
| - if "reports" in results and results["reports"]: |
95 |
| - reports = results["reports"] |
| 98 | + if 'reports' in results and results['reports']: |
| 99 | + reports = results['reports'] |
96 | 100 | for report in reports:
|
97 |
| - print ("Report from '%s' to '%s' downloadable at '%s'" |
98 |
| - % (report["startTime"], report["endTime"], report["downloadUrl"])) |
| 101 | + print ('Report dates: %s to %s\n download URL: %s\n' |
| 102 | + % (report['startTime'], report['endTime'], report['downloadUrl'])) |
99 | 103 |
|
100 | 104 |
|
101 | 105 | # Call the YouTube Reporting API's media.download method to download the report.
|
102 |
| -def download_report(youtube_reporting, report_url): |
| 106 | +def download_report(youtube_reporting, report_url, local_file): |
103 | 107 | request = youtube_reporting.media().download(
|
104 |
| - resourceName="" |
| 108 | + resourceName=' ' |
105 | 109 | )
|
106 | 110 | request.uri = report_url
|
107 |
| - fh = FileIO('report', mode='wb') |
| 111 | + fh = FileIO(local_file, mode='wb') |
108 | 112 | # Stream/download the report in a single request.
|
109 | 113 | downloader = MediaIoBaseDownload(fh, request, chunksize=-1)
|
110 | 114 |
|
111 | 115 | done = False
|
112 | 116 | while done is False:
|
113 | 117 | status, done = downloader.next_chunk()
|
114 | 118 | if status:
|
115 |
| - print "Download %d%%." % int(status.progress() * 100) |
116 |
| - print "Download Complete!" |
| 119 | + print 'Download %d%%.' % int(status.progress() * 100) |
| 120 | + print 'Download Complete!' |
117 | 121 |
|
118 | 122 |
|
119 |
| -# Prompt the user to enter a job id for report retrieval. Then return the id. |
| 123 | +# Prompt the user to select a job and return the specified ID. |
120 | 124 | def get_job_id_from_user():
|
121 |
| - job_id = raw_input("Please enter the job id for the report retrieval: ") |
122 |
| - print ("You chose '%s' as the job Id for the report retrieval." % job_id) |
| 125 | + job_id = raw_input('Please enter the job id for the report retrieval: ') |
| 126 | + print ('You chose "%s" as the job Id for the report retrieval.' % job_id) |
123 | 127 | return job_id
|
124 | 128 |
|
125 |
| - |
126 |
| -# Prompt the user to enter a report URL for download. Then return the URL. |
| 129 | +# Prompt the user to select a report URL and return the specified URL. |
127 | 130 | def get_report_url_from_user():
|
128 |
| - report_url = raw_input("Please enter the report URL to download: ") |
129 |
| - print ("You chose '%s' to download." % report_url) |
| 131 | + report_url = raw_input('Please enter the report URL to download: ') |
| 132 | + print ('You chose "%s" to download.' % report_url) |
130 | 133 | return report_url
|
131 | 134 |
|
132 |
| -if __name__ == "__main__": |
133 |
| - args = argparser.parse_args() |
134 |
| - |
135 |
| - youtube_reporting = get_authenticated_service(args) |
| 135 | +if __name__ == '__main__': |
| 136 | + parser = argparse.ArgumentParser() |
| 137 | + parser.add_argument('--content_owner', default='', |
| 138 | + help='ID of content owner for which you are retrieving jobs and reports') |
| 139 | + parser.add_argument('--job_id', default=None, |
| 140 | + help='ID of the job for which you are retrieving reports. If not ' + |
| 141 | + 'provided AND report_url is also not provided, then the script ' + |
| 142 | + 'calls jobs.list() to retrieve a list of jobs.') |
| 143 | + parser.add_argument('--report_url', default=None, |
| 144 | + help='URL of the report to retrieve. If not specified, the script ' + |
| 145 | + 'calls reports.list() to retrieve a list of reports for the ' + |
| 146 | + 'selected job.') |
| 147 | + parser.add_argument('--local_file', default='yt_report.txt', |
| 148 | + help='The name of the local file where the downloaded report will be written.') |
| 149 | + args = parser.parse_args() |
| 150 | + |
| 151 | + youtube_reporting = get_authenticated_service() |
136 | 152 | try:
|
137 |
| - if list_reporting_jobs(youtube_reporting): |
138 |
| - retrieve_reports(youtube_reporting, get_job_id_from_user()) |
139 |
| - download_report(youtube_reporting, get_report_url_from_user()) |
| 153 | + # If the user has not specified a job ID or report URL, retrieve a list |
| 154 | + # of available jobs and prompt the user to select one. |
| 155 | + if not args.job_id and not args.report_url: |
| 156 | + if list_reporting_jobs(youtube_reporting, |
| 157 | + onBehalfOfContentOwner=args.content_owner): |
| 158 | + args.job_id = get_job_id_from_user() |
| 159 | + |
| 160 | + # If the user has not specified a report URL, retrieve a list of reports |
| 161 | + # available for the specified job and prompt the user to select one. |
| 162 | + if args.job_id and not args.report_url: |
| 163 | + retrieve_reports(youtube_reporting, |
| 164 | + jobId=args.job_id, |
| 165 | + onBehalfOfContentOwner=args.content_owner) |
| 166 | + args.report_url = get_report_url_from_user() |
| 167 | + |
| 168 | + # Download the selected report. |
| 169 | + if args.report_url: |
| 170 | + download_report(youtube_reporting, args.report_url, args.local_file) |
140 | 171 | except HttpError, e:
|
141 |
| - print "An HTTP error %d occurred:\n%s" % (e.resp.status, e.content) |
142 |
| - else: |
143 |
| - print "Retrieved reports." |
| 172 | + print 'An HTTP error %d occurred:\n%s' % (e.resp.status, e.content) |
0 commit comments