How to use Google Blogger API with Python? - python

I'm trying to use the blog functions from Google API gdata. I tried my best following the documentation but I failed very badly. Can anybody tell me how can I use the Google blogger API? My code is pretty messed up and now I'm out of clue.
EDIT FULL WORKING CODE :) :
from oauth2client.client import OAuth2WebServerFlow
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
#flow = OAuth2WebServerFlow(client_id='', #ID
# client_secret='', #SECRET ID
# scope='https://www.googleapis.com/auth/blogger',
# redirect_uri='urn:ietf:wg:oauth:2.0:oob')
#auth_uri = flow.step1_get_authorize_url()
# Redirect the user to auth_uri on your platform.
# Open a file
#fo = open("foo.txt", "wb")
#fo.write( auth_uri +"\n");
#fo.close()
#credentials = flow.step2_exchange( raw_input ( ) )
storage = Storage('a_credentials_file')
#storage.put(credentials)
credentials = storage.get()
http = httplib2.Http()
http = credentials.authorize(http)
service = build('blogger', 'v3', http=http)
users = service.users()
# Retrieve this user's profile information
thisuser = users.get(userId='self').execute()
print('This user\'s display name is: %s' % thisuser['displayName'])

While I was myself trying to find a solution, I found this. Then after some modifications, the code finally worked. It successfully print all details about you blog site.
from oauth2client.client import flow_from_clientsecrets
import httplib2
from apiclient.discovery import build
from oauth2client.file import Storage
import webbrowser
def get_credentials():
scope = 'https://www.googleapis.com/auth/blogger'
flow = flow_from_clientsecrets(
'client_secrets.json', scope,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
storage = Storage('credentials.dat')
credentials = storage.get()
if not credentials or credentials.invalid:
auth_uri = flow.step1_get_authorize_url()
webbrowser.open(auth_uri)
auth_code = raw_input('Enter the auth code: ')
credentials = flow.step2_exchange(auth_code)
storage.put(credentials)
return credentials
def get_service():
"""Returns an authorised blogger api service."""
credentials = get_credentials()
http = httplib2.Http()
http = credentials.authorize(http)
service = build('blogger', 'v3', http=http)
return service
if __name__ == '__main__':
served = get_service()
blogs = served.blogs()
blog_get_obj = blogs.get(blogId='123456789123456')
details = blog_get_obj.execute()
print details
The results of print will look like:
{u'description': u'Look far and wide. There are worlds to conquer.',
u'id': u'8087466742945672359',
u'kind': u'blogger#blog',
u'locale': {u'country': u'', u'language': u'en', u'variant': u''},
u'name': u'The World Around us',
u'pages': {u'selfLink': u'https://www.googleapis.com/blogger/v3/blogs/1234567897894569/pages',
u'totalItems': 2},
u'posts': {u'selfLink': u'https://www.googleapis.com/blogger/v3/blogs/1245678992359/posts',
u'totalItems': 26},
u'published': u'2015-11-02T18:47:02+05:30',
u'selfLink': u'https://www.googleapis.com/blogger/v3/blogs/9874652945672359',
u'updated': u'2017-06-29T19:41:00+05:30',
u'url': u'http://www.safarnuma.com/'}

This is an updated and long-term stable implementation, taken from this answer and edited a bit for Blogger API v3.
All methods in the official documentation can be called on blogger_service variable of this code.
import os
import pickle
from googleapiclient.discovery import build
from google_auth_oauthlib.flow import InstalledAppFlow
from google.auth.transport.requests import Request
SCOPES = ['https://www.googleapis.com/auth/blogger', ]
# we check if the file to store the credentials exists
if not os.path.exists('credentials.dat'):
flow = InstalledAppFlow.from_client_secrets_file('credentials.json', SCOPES)
credentials = flow.run_local_server()
with open('credentials.dat', 'wb') as credentials_dat:
pickle.dump(credentials, credentials_dat)
else:
with open('credentials.dat', 'rb') as credentials_dat:
credentials = pickle.load(credentials_dat)
if credentials.expired:
credentials.refresh(Request())
blogger_service = build('blogger', 'v3', credentials=credentials)
users = blogger_service.users()
# Retrieve this user's profile information
thisuser = users.get(userId='self').execute()
print('Your display name is: %s' % thisuser['displayName'])

You can use goco
pip install goco
then use this code:
from goco import Goco
GoogleApi = Goco("path\\to\\client_secret.json", "path\\to\\credentials.storage")
MyBlog = GoogleApi.connect(scope='Blogger', service_name='blogger', version='v3')
Posts = MyBlog.posts().list(blogId='desired-blog-id').execute()
print(Posts)
you can also connect to any google service via this module.

Related

Youtube Data API v3 - Skip "Please visit this URL" & enter authorization code?

I'm trying to get the video list of my youtube channel and update it as i please, i've done it with .net & it's quite easy, But in python it's kind of disturbing each time i run the script i got the message of "Please visit this URL to authorize this application" Althought i use the same credentials.json file i use it on .net.
NB: No need to mark down this question for duplicate or anything because i already check many Many of the same question here on stackover like this , this & this other forums too but none seems to provide a clear concrete solution every solution so far i've tried has the same result.
Here's the sample code i'm using :
Any help will be much appreciated.
import os
import sys
file_path = os.path.dirname(__file__)
module_path = os.path.join(file_path, "lib")
sys.path.append(module_path)
import pickle
import google_auth_oauthlib.flow
import googleapiclient.discovery
import googleapiclient.errors
scopes = [
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.upload",
"https://www.googleapis.com/auth/youtubepartner",
"https://www.googleapis.com/auth/youtube.force-ssl",
]
client_secrets_file = "credentials.json"
api_service_name = "youtube"
api_version = "v3"
def main():
# Disable OAuthlib's HTTPS verification when running locally.
# *DO NOT* leave this option enabled in production.
os.environ["OAUTHLIB_INSECURE_TRANSPORT"] = "1"
# Get credentials and create an API client
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(
client_secrets_file, scopes)
youtube = get_authenticated_service()
request = youtube.channels().list(
part="contentDetails",
mine=True
)
response = request.execute()
print(response)
def get_authenticated_service():
if os.path.exists("CREDENTIALS_PICKLE_FILE"):
with open("CREDENTIALS_PICKLE_FILE", 'rb') as f:
credentials = pickle.load(f)
else:
flow = google_auth_oauthlib.flow.InstalledAppFlow.from_client_secrets_file(client_secrets_file, scopes)
credentials = flow.run_console()
with open("CREDENTIALS_PICKLE_FILE", 'wb') as f:
pickle.dump(credentials, f)
return googleapiclient.discovery.build(
api_service_name, api_version, credentials=credentials)
if __name__ == "__main__":
main()
I luckily found the solution to this problem, and here a sample working script that will list all the video you have in ur YouTube channel and will ask for authorization Code just one time.
i know it's a bit messy but it's ok
import os
import sys
file_path = os.path.dirname(__file__)
module_path = os.path.join(file_path, "lib")
sys.path.append(module_path)
import httplib2
import json
import argparse
import re
import random
from pytz import timezone
from dateutil import parser
from datetime import datetime
from googleapiclient.discovery import build
from oauth2client.client import flow_from_clientsecrets
from oauth2client.file import Storage
from oauth2client.tools import argparser, run_flow
random.seed()
CLIENT_SECRETS_FILE = "credentials.json"
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: %swith information from the Developers Console
""" % os.path.abspath(os.path.join(os.path.dirname(__file__),CLIENT_SECRETS_FILE))
scopes = [
"https://www.googleapis.com/auth/youtube",
"https://www.googleapis.com/auth/youtube.upload",
"https://www.googleapis.com/auth/youtubepartner",
"https://www.googleapis.com/auth/youtube.force-ssl",
]
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
flow = flow_from_clientsecrets(CLIENT_SECRETS_FILE,message=MISSING_CLIENT_SECRETS_MESSAGE, scope=scopes)
storage = Storage("%s-oauth2.json" % sys.argv[0])
credentials = storage.get()
if credentials is None or credentials.invalid:
flags = argparser.parse_args()
credentials = run_flow(flow, storage, flags)
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
http=credentials.authorize(httplib2.Http()))
channels_response = youtube.channels().list(
mine=True,
part="contentDetails"
).execute()
for channel in channels_response["items"]:
uploads_list_id = channel["contentDetails"]["relatedPlaylists"]["uploads"]
print("Videos in list {0:s}".format(uploads_list_id),file=sys.stderr)
playlistitems_list_request = youtube.playlistItems().list(
playlistId=uploads_list_id,
part="snippet",
maxResults=50
)
playlistitems_list_response = playlistitems_list_request.execute()
for playlist_item in playlistitems_list_response["items"]:
title = playlist_item["snippet"]["title"]
video_id = playlist_item["snippet"]["resourceId"]["videoId"]
video_list_request = youtube.videos().list(
id=video_id,
part="snippet,fileDetails,statistics,status",
maxResults=50
)
video_list_response = video_list_request.execute()
for video_list_item in video_list_response["items"]:
print(title)
print (video_id)
print (video_list_item["fileDetails"]["fileName"])
print (video_list_item["statistics"]["viewCount"])
print (video_list_item["statistics"]["likeCount"])
print (video_list_item["snippet"]["description"])
print (video_list_item["snippet"]["publishedAt"])
print (video_list_item["status"]["privacyStatus"])

Google Developer API upload APK using Python

I am trying to upload an APK to Google Play using the Developer API. I have a Python script that mostly works, but the upload keeps returning a "HttpError 403 when requesting 'APK size too big'" error. We have had no problems uploading and releasing the app manually through the web interface. Am I missing a setting somewhere?
Here is my current script:
import argparse
from googleapiclient.discovery import build
import google_auth_httplib2
import httplib2
from oauth2client import client
from google.oauth2 import service_account
from google.auth.transport.requests import Request
import sys, os, socket
def main():
pathname = os.path.dirname(sys.argv[0])
fullpath = os.path.abspath(pathname)
SCOPES = ['https://www.googleapis.com/auth/androidpublisher']
SERVICE_ACCOUNT_FILE = fullpath + '/authorization_data.json' # access keys json file
credentials = service_account.Credentials.from_service_account_file(SERVICE_ACCOUNT_FILE, scopes=SCOPES)
credentials.refresh(Request())
print(credentials.token)
http = httplib2.Http(timeout=300)
http = google_auth_httplib2.AuthorizedHttp(credentials, http=http)
service = build('androidpublisher', 'v3', http=http)
package_name = 'com.company.app'
apk_file = 'upload/myapp.apk'
try:
print('creating edit')
edit_request = service.edits().insert(body={}, packageName=package_name)
result = edit_request.execute()
edit_id = result['id']
print('id: ' + edit_id)
print('uploading apk')
apk_response = service.edits().apks().upload(
editId=edit_id,
packageName=package_name,
media_body=apk_file
).execute()
print('Version code %d has been uploaded' % apk_response['versionCode'])
print('committing edit')
commit_request = service.edits().commit(
editId=edit_id,
packageName=package_name
).execute()
print('Edit "%s" has been committed' % commit_request['id'])
except client.AccessTokenRefreshError:
print('The credentials have been revoked or expired, please re-run the application to re-authorize')
if __name__ == '__main__':
main()

Serialize and de-serialize oauth2client.client.OAuth2Credentials

So I have an object, which is credentials from an OAuth2 authorization for a web service. I want to save the users credentials so I can continue to use them in the future. I'm using Django.
The object is: <oauth2client.client.OAuth2Credentials object at 0x104b47310>
I'm not sure how I can stringify the credentials and then build the credentials object back from a string.
Sample code as requested:
#!/usr/bin/python
import httplib2
from apiclient import errors
from apiclient.discovery import build
from oauth2client.client import OAuth2WebServerFlow
# Copy your credentials from the console
CLIENT_ID = 'YOUR_CLIENT_ID'
CLIENT_SECRET = 'YOUR_CLIENT_SECRET'
# Check https://developers.google.com/webmaster-tools/search-console-api-original/v3/ for all available scopes
OAUTH_SCOPE = 'https://www.googleapis.com/auth/webmasters.readonly'
# Redirect URI for installed apps
REDIRECT_URI = 'urn:ietf:wg:oauth:2.0:oob'
# Run through the OAuth flow and retrieve credentials
flow = OAuth2WebServerFlow(CLIENT_ID, CLIENT_SECRET, OAUTH_SCOPE, REDIRECT_URI)
authorize_url = flow.step1_get_authorize_url()
print 'Go to the following link in your browser: ' + authorize_url
code = raw_input('Enter verification code: ').strip()
credentials = flow.step2_exchange(code)
# Create an httplib2.Http object and authorize it with our credentials
http = httplib2.Http()
http = credentials.authorize(http)
webmasters_service = build('webmasters', 'v3', http=http)
# Retrieve list of properties in account
site_list = webmasters_service.sites().list().execute()
# Filter for verified websites
verified_sites_urls = [s['siteUrl'] for s in site_list['siteEntry']
if s['permissionLevel'] != 'siteUnverifiedUser'
and s['siteUrl'][:4] == 'http']
# Printing the URLs of all websites you are verified for.
for site_url in verified_sites_urls:
print site_url
# Retrieve list of sitemaps submitted
sitemaps = webmasters_service.sitemaps().list(siteUrl=site_url).execute()
if 'sitemap' in sitemaps:
sitemap_urls = [s['path'] for s in sitemaps['sitemap']]
print " " + "\n ".join(sitemap_urls)
You can use pickle module to serialize and de-serialize python objects. Here is untested code:
import pickle
# Store OAuth2Credentials to a file
with open(FILENAME, 'wb') as credentials_file:
pickle.dump(credentials, credentials_file)
# Read OAuth2Credentials from file
with open(FILENAME, 'rb') as credentials_file:
credentials = pickle.load(credentials_file)

Upgrading a Python Script from oauth2client to google-auth

I would like to upgrade the following code from oauth2client to google-auth. Yes, this code does work and is a copy paste from the Google demo on their site.
from __future__ import print_function
from googleapiclient.discovery import build
from httplib2 import Http
from oauth2client import file, client, tools
# If modifying these scopes, delete the file token.json.
SCOPES = 'https://www.googleapis.com/auth/presentations.readonly'
# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'
def main():
"""Shows basic usage of the Slides API.
Prints the number of slides and elments in a sample presentation.
"""
# The file token.json stores the user's access and refresh tokens, and is
# created automatically when the authorization flow completes for the first
# time.
# delete the file to for authentication and authorization again
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
# credentials.json is issued by Google for the application
flow = client.flow_from_clientsecrets('credentials.json', SCOPES)
creds = tools.run_flow(flow, store)
service = build('slides', 'v1', http=creds.authorize(Http()))
# Call the Slides API
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
if __name__ == '__main__':
main()
I was able to upgrade most of it (I think) but could not find the equivalent for tools.run_flow using google-auth. Below is my upgraded version, and it has everything (I think) except the mechanism to do tools.run_flow. How is tools.run_flow accomplished using google-auth?
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
PRESENTATION_ID = '<some id>'
credentials = service_account.Credentials.from_service_account_file(
"the-json-file.json",
scopes=SCOPES
)
service = build('slides', 'v1', credentials=credentials)
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
When I run the above code using the google-auth approach, I get the following result:
googleapiclient.errors.HttpError: <HttpError 403 when requesting https://slides.googleapis.com/v1/presentations/<some id>?alt=json returned "The caller does not have permission">
Additional context, I am trying to build a Python script which accesses Google Slides to perform some processing on slide content. I am reading only, not writing to Google Slides. The code above is my attempt to handle the authentication and authorization part of accessing the Google Slides content for my GSuite account (I am the admin of my organization's GSuite). The first example using the older oauth2client works great, but since oauth2client is deprecated and google-auth is recommended I would like to do it the "right" way using the latest library.
UPDATE
I resolved part of my problem with the following code:
from google.oauth2 import service_account
from google.auth.transport.requests import AuthorizedSession
from googleapiclient.discovery import build
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
import os
import json
def get_credentials():
CLIENT_SECRET_FILE = '<some file>'
SCOPES = ['https://www.googleapis.com/auth/presentations.readonly']
credentials_path = '<some path>/token.json'
if os.path.exists(credentials_path):
# expect these to be valid. may expire at some point, but should be refreshed by google api client...
return Credentials.from_authorized_user_file(credentials_path, scopes=SCOPES)
else:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE,
scopes=SCOPES,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
auth_url, _ = flow.authorization_url(prompt='consent')
print('Please go to this URL and finish the authentication flow: {}'.format(auth_url))
code = input('Enter the authorization code: ')
flow.fetch_token(code=code)
credentials = flow.credentials
credentials_as_dict = {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'id_token': credentials.id_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret
}
with open(credentials_path, 'w') as file:
file.write(json.dumps(credentials_as_dict))
return credentials
# The ID of a sample presentation.
PRESENTATION_ID = '<some id>'
service = build('slides', 'v1', credentials=get_credentials())
presentation = service.presentations().get(presentationId=PRESENTATION_ID).execute()
slides = presentation.get('slides')
print('The presentation contains {} slides:'.format(len(slides)))
for i, slide in enumerate(slides):
print('- Slide #{} contains {} elements.'.format(
i + 1, len(slide.get('pageElements'))))
My challenge now is causing the web browser to open automatically. I can copy and paste the link and get the code manually and it all works. Ideally, I would like the automatic opening of the web browser and capturing of the token like it did in the older library.
SOLVED
Update a section code in the previous code sample to this:
flow = InstalledAppFlow.from_client_secrets_file(
CLIENT_SECRET_FILE,
scopes=SCOPES,
redirect_uri='urn:ietf:wg:oauth:2.0:oob')
credentials = flow.run_local_server()
credentials_as_dict = {
'token': credentials.token,
'refresh_token': credentials.refresh_token,
'id_token': credentials.id_token,
'token_uri': credentials.token_uri,
'client_id': credentials.client_id,
'client_secret': credentials.client_secret
}
Web browser opens automatically and captures the token value. All is good.

Creating a DfpClient with a Service Account in Python

I use the google DFP api to collect some statistics on ads clicked on our website. The
code is written in Python. Currently, I am trying to upgrade the code to use oAuth 2.
Since, the code runs automatically everyday without any user involvement, I created a
service account under my google project and added the account to the DoubleClick for
Publishers network of our company. Based on the sample codes on the web, I wrote this:
import httplib2
from oauth2client.client import SignedJwtAssertionCredentials
from apiclient.discovery import build
from googleads.dfp import DfpClient
GOOGLE_DFP_SCOPE="https://www.googleapis.com/auth/dfp"
API_VERSION="v201411"
KEY_FILE="*******.p12"
ACCT_EMAIL="************************#developer.gserviceaccount.com"
NETWORK_CODE="**********"
with open(KEY_FILE) as config_file:
my_private_key = config_file.read()
credentials = SignedJwtAssertionCredentials(service_account_name=ACCT_EMAIL, private_key=my_private_key,scope=GOOGLE_DFP_SCOPE)
http = httplib2.Http()
http_auth = credentials.authorize(http)
dfp_client = build(serviceName='dfp',version=API_VERSION,http=http_auth)
This code does not seem to be correct, because the network_code has not been passed
anywhere in the code. In addition, it fails with the following message:
apiclient.errors.UnknownApiNameOrVersion: name: dfp version: v201411.
Also, the line below:
dfp_client = DfpClient.LoadFromStorage()
does not work for my case, because, this is based on googleads.yaml which seems
to be formatted only for web-app accounts with client secret, not P12 private key.
Any advice? Thanks.
Apiclient.discovery uses a default route to check the services.
But I did not find a service for DoubleClick for publishers.
I use this code to use API with Oauth2. Using Flask
import json
import requests
import flask
from googleads import dfp
from googleads import oauth2
app = flask.Flask(__name__)
CLIENT_ID = ''
CLIENT_SECRET = '' # Read from a file or environmental variable in a real app
SCOPE = 'https://www.googleapis.com/auth/dfp'
REDIRECT_URI = ''
APPLICATION_NAME = 'DFP API SERVICE'
NETWORK_CODE = ''
#app.route('/')
def index():
if 'credentials' not in flask.session:
return flask.redirect(flask.url_for('oauth2callback'))
credentials = json.loads(flask.session['credentials'])
if credentials['expires_in'] <= 0:
return flask.redirect(flask.url_for('oauth2callback'))
else:
try:
refresh_token = credentials['refresh_token']
oauth2_client = oauth2.GoogleRefreshTokenClient(CLIENT_ID, CLIENT_SECRET, refresh_token)
dfp_client = dfp.DfpClient(oauth2_client, APPLICATION_NAME, NETWORK_CODE)
user_service = dfp_client.GetService('UserService', version='v201508')
user = user_service.getCurrentUser()
return flask.render_template('index.html', name=user['name'])
except:
flask.session.pop('credentials', None)
return flask.redirect(flask.url_for('oauth2callback'))
#app.route('/oauth2callback')
def oauth2callback():
if 'code' not in flask.request.args:
auth_uri = ('https://accounts.google.com/o/oauth2/auth?response_type=code'
'&access_type=offline&client_id={}&redirect_uri={}&scope={}&').format(CLIENT_ID, REDIRECT_URI, SCOPE)
return flask.redirect(auth_uri)
else:
auth_code = flask.request.args.get('code')
data = {'code': auth_code,
'client_id': CLIENT_ID,
'client_secret': CLIENT_SECRET,
'redirect_uri': REDIRECT_URI,
'grant_type': 'authorization_code'}
r = requests.post('https://www.googleapis.com/oauth2/v3/token', data=data)
flask.session['credentials'] = r.text
return flask.redirect(flask.url_for('index'))
if __name__ == '__main__':
import uuid
app.secret_key = str(uuid.uuid4())
app.debug = False
app.run()
I hope this help you
You are correct. You have to pass the network code when you create a dfp client. And version is not necessary. Try the following code to create the client in python.
import os
from googleads import oauth2
from googleads import dfp
def get_dfp_client():
application_name = "Your application name" # from google developer console. eg: Web Client
network_code = ********
private_key_password = 'notasecret'
key_file = os.path.join('path/to/p12file')
service_account_email = '****#***.iam.gserviceaccount.com'
# create oath2 client(google login)
oauth2_client = oauth2.GoogleServiceAccountClient(
oauth2.GetAPIScope('dfp'), service_account_email, key_file)
dfp_client = dfp.DfpClient(oauth2_client, application_name, network_code)
return dfp_client
client = get_dfp_client()
Reference
Please comment if you need more clarification.
Update
googleads renamed module dfp to ad_manager, docs here – Gocht

Categories

Resources