|
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