I cannot create a simple Ad with an external link to a mobile app. I have properly set access, can create a Campaign, an AdSet, load an image, but during an Ad creation I get an error:
Ads and ad creatives must be associated with a Facebook Page. Try connecting your ad or ad creative to a Page and resubmit your ad.
But I have associated a page! Here is my code:
# No problem with these ones
adset = ...
image_hash = '...'
url = 'https://itunes.apple.com/app/96...'
page_id = '25036...'
# Create an Ad Creative
creative = AdCreative()
creative['_parent_id'] = my_ads_acc_id
creative[AdCreative.Field.title] = 'Aivan Test Creative'
creative[AdCreative.Field.body] = 'Aivan Test Ad Creative Body'
creative[AdCreative.Field.actor_id] = page_id
creative[AdCreative.Field.link_url] = url
creative[AdCreative.Field.object_url] = url
creative[AdCreative.Field.object_type] = AdCreative.ObjectType.domain
creative[AdCreative.Field.call_to_action_type] = AdCreative.CallToActionType.use_mobile_app
creative[AdCreative.Field.image_hash] = image_hash
# Create an Ad
ad = Ad()
ad['_parent_id'] = my_ads_acc_id
ad[Ad.Field.name] = 'Aivan Ad'
ad[Ad.Field.adset_id] = adset[AdSet.Field.id]
ad[Ad.Field.creative] = creative
# This line generates an exception:
ad.remote_create(params={
'status': Ad.Status.paused,
})
I have specified the actor_id field, also I have tried other different code samples, but nothing works well. How can I connect a page?
Additional info:
My app is in development mode. I cannot turn the production mode because it needs a review which needs a completed app.
I have tried to use object_story_spec with link_data in it, but it creates other error because it doesn't work in development mode.
The app and the page are linked with Facebook Business Manager.
The results is the same if I init the API with app token or system user token: FacebookAdsApi.init(app_id, app_secret, app_access_token / system_user_token). The system user has access to both Ads Account and the Page.
I've solved the problem a long time ago, and since that time my server app successfully created lots of Facebook ads of both types, for websites and mobile apps. The first step to solve the problem was to understand that these ads types are completely different on Facebook, they need different settings for Campaign, AdSet & Ad. Here is my code for mobile ads creation.
1) Create Campaign object. account_id must be the ID of your Ad Account.
campaign = Campaign()
campaign['_parent_id'] = account_id
campaign[Campaign.Field.name] = 'Some Campaign Name'
campaign[Campaign.Field.objective] = 'APP_INSTALLS'
campaign.remote_create()
campaign_id = str(campaign[Campaign.Field.id])
2) Create AdSet object.
adset = AdSet()
adset['_parent_id'] = account_id
adset.update({
AdSet.Field.name: 'Some AdSet Name',
AdSet.Field.campaign_id: campaign_id,
AdSet.Field.lifetime_budget: budget * 100,
AdSet.Field.bid_strategy: 'LOWEST_COST_WITHOUT_CAP',
AdSet.Field.billing_event: AdSet.BillingEvent.link_clicks,
AdSet.Field.optimization_goal: AdSet.OptimizationGoal.link_clicks,
AdSet.Field.promoted_object: {
'object_store_url': app_store_url,
'application_id': ad_app_id,
},
AdSet.Field.targeting: targeting_object,
AdSet.Field.start_time: '2018-12-01 00:00:00',
AdSet.Field.end_time: '2018-12-30 23:59:00',
})
adset.remote_create()
adset_id = str(adset[AdSet.Field.id])
Note that to create mobile ad, you initially need to register your mobile app as a Facebook app (here you will get ad_app_id) and specify links to Apple App Store and Google Play Market. So, the value of app_store_url must be equal to one of those links in your Facebook app settings. Unfortunately, app can be registered only manually (if you know how to do it programmatically – write a comment, please).
Also note that billing_event and optimization_goal are connected with ads type (mobile/web) and with each other, you cannot just choose another one. (But if you know that this is possible, or there are some docs on this topics – let me know.)
budget is a money amount in the currency of your Ad Account. You can specify either lifetime_budget or something like day_budget, read the docs about it.
3) Then, you have to create AdCreative object with some other sub objects. Note that some of these lines of code are necessary for FB ad only, others for IG, others for both of them, but together they work well for everything. You can find description for all the formats here.
link_data = AdCreativeLinkData()
link_data[AdCreativeLinkData.Field.name] = main_text
link_data[AdCreativeLinkData.Field.message] = title
link_data[AdCreativeLinkData.Field.link] = app_store_url
link_data[AdCreativeLinkData.Field.image_hash] = image_hash
link_data[AdCreativeLinkData.Field.call_to_action] = {
'type': 'INSTALL_MOBILE_APP',
'value': {
'application': ad_app_id,
'link': app_store_url,
},
}
object_story_spec = AdCreativeObjectStorySpec()
object_story_spec[AdCreativeObjectStorySpec.Field.page_id] = page_id
object_story_spec[AdCreativeObjectStorySpec.Field.link_data] = link_data
creative = AdCreative()
creative['_parent_id'] = account_id
creative[AdCreative.Field.object_story_spec] = object_story_spec
creative[AdCreative.Field.title] = main_text
creative[AdCreative.Field.body] = title
creative[AdCreative.Field.actor_id] = page_id
creative[AdCreative.Field.link_url] = app_store_url
creative[AdCreative.Field.image_hash] = image_hash
To upload an image and get image_hash, check out this doc. The page_id must be an ID of the page which name and logo will be shown as the author of the ad.
You must note that the user, who creates the ad, must have an access to this page, to the mobile app registered on FB (ad_app_id), and to the Ad Account (account_id). In my server application I use Facebook system users for all the work with API.
4) And finally, create the Ad object itself:
ad = Ad()
ad['_parent_id'] = account_id
ad[Ad.Field.name] = 'Some Ad Name'
ad[Ad.Field.adset_id] = adset_id
ad[Ad.Field.creative] = creative
ad.remote_create(params={
'status': Ad.Status.active,
})
ad_id = str(ad[Ad.Field.id])
That's all!
Maybe someone will need to use or just want to see the difference when creating FB/IG ads for websites, it is a little bit simpler. So, here is my code for website ads creation.
1) Create Campaign object. Notice that website ads has a different objective. account_id must be the ID of your Ad Account.
campaign = Campaign()
campaign['_parent_id'] = account_id
campaign[Campaign.Field.name] = 'Some Campaign Name'
campaign[Campaign.Field.objective] = 'LINK_CLICKS'
campaign.remote_create()
campaign_id = str(campaign[Campaign.Field.id])
2) Create AdSet object. Note that billing_event and optimization_goal are connected with ads type (mobile/web) and with each other. Also, here you don't need to specify promoted_object in the AdSet.
adset = AdSet()
adset['_parent_id'] = account_id
adset.update({
AdSet.Field.name: 'Some AdSet Name',
AdSet.Field.campaign_id: campaign_id,
AdSet.Field.lifetime_budget: budget * 100,
AdSet.Field.bid_strategy: 'LOWEST_COST_WITHOUT_CAP',
AdSet.Field.billing_event: AdSet.BillingEvent.impressions,
AdSet.Field.optimization_goal: AdSet.OptimizationGoal.reach,
AdSet.Field.targeting: targeting_object,
AdSet.Field.start_time: '2018-12-01 00:00:00',
AdSet.Field.end_time: '2018-12-30 23:59:00',
})
adset.remote_create()
adset_id = str(adset[AdSet.Field.id])
Rules for budget are the same: budget is a money amount in the currency of your Ad Account. You can specify either lifetime_budget or something like day_budget, read the docs about it.
3) Then, you have to create AdCreative object with some other sub objects. You can find description for all the formats here.
link_data = AdCreativeLinkData()
link_data[AdCreativeLinkData.Field.name] = main_text
link_data[AdCreativeLinkData.Field.message] = title
link_data[AdCreativeLinkData.Field.link] = website_url
link_data[AdCreativeLinkData.Field.image_hash] = image_hash
object_story_spec = AdCreativeObjectStorySpec()
object_story_spec[AdCreativeObjectStorySpec.Field.page_id] = page_id
object_story_spec[AdCreativeObjectStorySpec.Field.link_data] = link_data
creative = AdCreative()
creative['_parent_id'] = account_id
creative[AdCreative.Field.object_story_spec] = object_story_spec
creative[AdCreative.Field.title] = main_text
creative[AdCreative.Field.body] = title
creative[AdCreative.Field.actor_id] = page_id
creative[AdCreative.Field.link_url] = website_url
creative[AdCreative.Field.object_type] = AdCreative.ObjectType.domain
creative[AdCreative.Field.image_hash] = image_hash
To upload an image and get image_hash, check out this doc. The page_id must be an ID of the page which name and logo will be shown as the author of the ad. Note that the user, who creates the ad, must have an access to this page, to the mobile app registered on FB (ad_app_id), and to the Ad Account (account_id).
4) And finally, create the Ad object itself:
ad = Ad()
ad['_parent_id'] = account_id
ad[Ad.Field.name] = 'Some Ad Name'
ad[Ad.Field.adset_id] = adset_id
ad[Ad.Field.creative] = creative
ad.remote_create(params={
'status': Ad.Status.active,
})
ad_id = str(ad[Ad.Field.id])
As you can see, to promote websites you don't need to register them on Facebook (in contrast to mobile ads).
Related
I am trying to create a service account via the Ldap3 library in Python. The service account is successfully created, but there is a small problem. The "User cannot change password" checkboxes is not selected.
I did some research and found that to set this property I need to follow some steps given here : https://learn.microsoft.com/en-us/windows/win32/adsi/modifying-user-cannot-change - password-ldap-provider . The logic given in this link is in a different programming language than Python, so i tried to replicate the same logic in Python. From what we understand, I’ve implemented the feature, which executed successfully, but didn't see the expected effect on the AD server ("User cannot change password" checkbox is still unchecked).
Below is the code used to create and add the ACL object to the service account.
def create_object_ace(privguid, sid):
print("creating ace object")
nace = ldaptypes.ACE()
nace['AceType'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_TYPE
nace['AceFlags'] = 0x00
acedata = ldaptypes.ACCESS_DENIED_OBJECT_ACE()
acedata['Mask'] = ldaptypes.ACCESS_MASK()
acedata['Mask']['Mask'] = ldaptypes.ACCESS_ALLOWED_OBJECT_ACE.ADS_RIGHT_DS_CONTROL_ACCESS
acedata['ObjectType'] = string_to_bin(privguid)
acedata['InheritedObjectType'] = b''
acedata['Sid'] = ldaptypes.LDAP_SID()
acedata['Sid'].fromCanonical(sid)
assert sid == acedata['Sid'].formatCanonical()
acedata['Flags'] = ldaptypes.ACCESS_DENIED_OBJECT_ACE.ACE_OBJECT_TYPE_PRESENT
nace['Ace'] = acedata
return nace
s = Server('ad_server.com', get_info=ALL)
c = Connection(s, user="testdomain\\username", password="password", authentication=NTLM)
c.search(search_base="DC=testad,DC=com", search_filter="(CN=svc_account_47)",
search_scope=SUBTREE, attributes=['objectSid', 'sAMAccountName'])
entry = c.entries[0]
usersid = entry['objectSid'].value
controls = security_descriptor_control(sdflags=0x04)
c.search(search_base="DC=testahs,DC=com", search_filter='(&(objectCategory=domain))',
attributes=['SAMAccountName', 'nTSecurityDescriptor'], controls=controls)
entry = c.entries[0]
secDescData =. entry['nTSecurityDescriptor'].raw_values[0]
secDesc = ldaptypes.SR_SECURITY_DESCRIPTOR(data=secDescData)
secDesc['Dacl']['Data'].append(create_object_ace('ab721a53-1e2f-11d0-9819-00aa0040529b', usersid)) # This GUID is for 'User cannot change password'
dn = entry.entry_dn
data = secDesc.getData()
c.modify(dn, {'nTSecurityDescriptor': (ldap3.MODIFY_REPLACE, [data])}, controls=controls)
print(c.result)
# gives -> {'result': 0, 'description': 'success', 'dn': '', 'message': '', 'referrals': None, 'type': 'modifyResponse'}
The Python code reference is from the following link:
https://github.com/SecureAuthCorp/impacket/blob/master/impacket/examples/ntlmrelayx/attacks/ldapattack.py
Can someone help me here. Thanks in advance.
I have been trying to fetch data from Google Analytics using its python API but its not returning data for all the entries in the field in ga:sourceMedium as df['ga:sourceMedium'].unique() returns: array(['google / cpc'], dtype=object) but there are several others sources and mediums present on Google Analytics. I am using correct parameters as far as I know but here are they in case I am not:
SCOPES = ['https://www.googleapis.com/auth/analytics.readonly']
KEY_FILE_LOCATION = 'GA_credentials.json'
VIEW_ID = '56495678'
SHEET_ID = ''
DIMENSIONS = ['ga:date','ga:sourceMedium','ga:campaign']
METRICS = ['ga:impressions', 'ga:adClicks','ga:adCost']
startDate = '2018-01-01'
endDate = 'today'
pageToken = '2000'
pageSize = '100000'
Any help/hint is highly appreciated! Thanks!
'ga:impressions', 'ga:adClicks', 'ga:adCost' are metrics of Google Ads, they cannot be associated with a medium such as referral or organic so you are returned those of Google Ads, precisely cpc.
basically im trying to write a index route that returns the posts of a business that a user is subscribed to
the last line is throwing an error for the backref (business.posts)
# query that finds all the subscriptions of the logged in user
subscriptions_query = models.Subscription.select().join(models.User).where(models.User.id == current_user.id)
# gets the businesses being followed from the subscriptions
businesses_being_followed = [subscription.following for subscription in subscriptions_query]
post_dicts = [model_to_dict(business.posts) for business in businesses_being_followed]
this is my posts model
class Post(BaseModel):
business = ForeignKeyField(Business, backref='posts')
image = CharField()
content = CharField()
date = DateTimeField(default=datetime.datetime.now)
Your example is REALLY inefficient.
Can you just do:
(Post
.select()
.join(Business)
.join(Subscription)
.where(Subscription.user == the_user_id))
I am working on a Python script that will import all my existing invoices to an Odoo 12 instance. I am using odoorpc library to simplify RPC calls to my Odoo instance.
I achieved to create an invoice using the API, registering it in "draft" state. Then, I want to "validate" it and update its state into "open". Unfortunately, using the "Validate" button in Odoo UI or calling the action from the RPC API do the same: invoice state is changed to "paid". I don't understand this behavior, since I didn't register any payment (it will be my next goal).
Here is a simplified version of my script that can be used to reproduce the issue :
import odoorpc
import settings
"""settings module contains various constants used
to connect with Odoo on my VPS"""
if __name__ == "__main__":
odoo = odoorpc.ODOO(settings.ODOO_HOST, port=settings.ODOO_PORT, timeout=10)
odoo.login(settings.ODOO_DB, settings.ODOO_USER, settings.ODOO_PASSWORD)
Partner = odoo.env["res.partner"]
# This partner already exists in DB
customer = Partner.browse([22])
Invoice = odoo.env["account.invoice"]
invoice_id = Invoice.create({
'partner_id' : customer.id,
'state': 'draft',
# This is ID for "Customers Invoices" journal
'journal_id': 1,
'account_id': customer.property_account_receivable_id.id,
# This is ID for default bank account, already registered
'partner_bank_id': 1,
'payment_term_id': odoo.env.ref("account.account_payment_term_net").id,
})
InvoiceLine = odoo.env["account.invoice.line"]
InvoiceLine.create({
"invoice_id": invoice_id,
"name": "A basic product",
"quantity": 6,
"price_unit": 100.0,
# Not sure about this one:
"uom_id": 1,
# No tax
"invoice_line_tax_ids": [],
'journal_id': 1,
'account_id': customer.property_account_receivable_id.id,
})
inv = Invoice.browse([invoice_id])
print("Before validating:", inv.state)
inv.action_invoice_open()
inv = Invoice.browse([invoice_id])
print("After validating:", inv.state)
result:
Before validating: draft
After validating: paid
I think there is something missing or wrong in my invoice creation, but I didn't find what exactly should be modified to have an invoice created the same way it would be from the UI.
Can anybody help me to find what's wrong in my script ?
I found myself a solution. It seems the account_id must be different for invoice and invoice line. To fix the issue, I retrieved the account.journal instance with ID 1 (for "Customers Invoices" journal), then used it to fill invoice line's account_id based on the journal's default_credit_account_id field:
cust_invoices_journal = odoo.env["account.journal"].browse([1])
# [...]
invoice_id = Invoice.create({
# [...]
'journal_id': cust_invoices_journal.id,
'account_id': customer.property_account_receivable_id.id,
# [...]
})
# [...]
InvoiceLine.create({
# [...]
'account_id': cust_invoices_journal.default_credit_account_id.id,
# [...]
})
I'm trying to get a RaspberryPi3 Python based birdhouse reading the popularity of its own uploaded videos (which enables it to deduct which ones should be deleted and avoid hundreds of uploaded files).
I thought the best way to read #views/#likes, was to use yt_analytics_report.py
When I input it always returns 0 values:
When I input:
$python yt_analytics_report.py --filters="video==bb_o--nP1mg"
or
$python yt_analytics_report.py --filters="channel==UCGXIq7h2UeFh9RhsSEsFsiA"
The output is:
$ python yt_analytics_report.py --filters="video==bb_o--nP1mg"
{'metrics': 'views,estimatedMinutesWatched,averageViewDuration', 'filters': 'video==bb_o--nP1mg', 'ids': 'channel==MINE', 'end_date': '2018-01-12', 'start_date': '2018-01-06'}
Please visit this URL to authorize this application: [note: here was url with authe sequence etc. which I ackced] followed by the result:
views estimatedMinutesWatched averageViewDuration
0.0 0.0 0.0
I'm new to this; The last 3 days I've been testing a variety of filters, but the result is always the same. I guess I do something severely wrong.
The (auto sensor triggered) video uploads work excellent so I presume the root cause is related to the way I'm using the yt-analytics example.
Any suggestions on rootcause or alternative methods to retrieve #views/#likes of self uploaded youtubes are appreciated.
After a few days trying I have found a solution how to generate with Python and the Youtube API v3 a list which contains views, likes etc of uploaded videos of my own Youtube channel.
I would like to share the complete code just in case anyone is having the same challenge. The code contains remarks and referrals to additional information.
Please be aware that using the API consumes API-credits... This implies that (when you run this script continuesly or often) you can run out of your daily maximum numbers of API-credits set by Google.
# This python 2.7.14 example shows how to retrieve with Youtube API v3 a list of uploaded Youtube videos in a channel and also
# shows additional statistics of each individual youtube video such as number of views, likes etc.
# Please notice that YOU HAVE TO change API_KEY and Youtube channelID
# Have a look at the referred examples to get to understand how the API works
#
# The code consists of two parts:
# - The first part queries the videos in a channel and stores it in a list
# - The second part queries in detail each individual video
#
# Credits to the Coding 101 team, the guy previously guiding me to a query and Google API explorer who/which got me on track.
#
# RESULTING EXAMPLE OUTPUT: The output of the will look a bit like this:
#
# https://www.youtube.com/watch?v=T3U2oz_Y8T0
# Upload date: 2018-01-13T09:43:27.000Z
# Number of views: 8
# Number of likes: 2
# Number of dislikes: 0
# Number of favorites:0
# Number of comments: 0
#
# https://www.youtube.com/watch?v=EFyC8nhusR8
# Upload date: 2018-01-06T14:24:34.000Z
# Number of views: 6
# Number of likes: 2
# Number of dislikes: 0
# Number of favorites:0
# Number of comments: 0
#
#
import urllib #importing to use its urlencode function
import urllib2 #for making http requests
import json #for decoding a JSON response
#
API_KEY = 'PLACE YOUR OWN YOUTUBE API HERE' # What? How? Learn here: https://www.youtube.com/watch?v=JbWnRhHfTDA
ChannelIdentifier = 'PLACE YOUR OWN YOUTUBE channelID HERE' # What? How? Learn here: https://www.youtube.com/watch?v=tf42K4pPWkM
#
# This first part will query the list of videos uploaded of a specific channel
# The identification is done through the ChannelIdentifier hwich you have defined as a variable
# The results from this first part will be stored in the list videoMetadata. This will be used in the second part of the code below.
#
# This code is based on the a very good example from Coding 101 which you can find here:https://www.youtube.com/watch?v=_M_wle0Iq9M
#
url = 'https://www.googleapis.com/youtube/v3/search?part=snippet&channelId='+ChannelIdentifier+'&maxResults=50&type=video&key='+API_KEY
response = urllib2.urlopen(url) #makes the call to YouTube
videos = json.load(response) #decodes the response so we can work with it
videoMetadata = [] #declaring our list
for video in videos['items']:
if video['id']['kind'] == 'youtube#video':
videoMetadata.append(video['id']['videoId']) #Appends each videoID and link to our list
#
# In this second part, a loop will run through the listvideoMetadata
# During each step the details a specific video are retrieved and displayed
# The structure of the API-return can be tested with the API explorer (which you can excecute without OAuth):
# https://developers.google.com/apis-explorer/#p/youtube/v3/youtube.videos.list?part=snippet%252CcontentDetails%252Cstatistics&id=Ks-_Mh1QhMc&_h=1&
#
for metadata in videoMetadata:
print "https://www.youtube.com/watch?v="+metadata # Here the videoID is printed
SpecificVideoID = metadata
SpecificVideoUrl = 'https://www.googleapis.com/youtube/v3/videos?part=snippet%2CcontentDetails%2Cstatistics&id='+SpecificVideoID+'&key='+API_KEY
response = urllib2.urlopen(SpecificVideoUrl) #makes the call to a specific YouTube
videos = json.load(response) #decodes the response so we can work with it
videoMetadata = [] #declaring our list
for video in videos['items']:
if video['kind'] == 'youtube#video':
print "Upload date: "+video['snippet']['publishedAt'] # Here the upload date of the specific video is listed
print "Number of views: "+video['statistics']['viewCount'] # Here the number of views of the specific video is listed
print "Number of likes: "+video['statistics']['likeCount'] # etc
print "Number of dislikes: "+video['statistics']['dislikeCount']
print "Number of favorites:"+video['statistics']['favoriteCount']
print "Number of comments: "+video['statistics']['commentCount']
print "\n"
Building on Sefo's answer above, I was able to clean up the outputs a bit.
The first function creates a list of relevant videos (you could replace this however you want), and the second iterates through this list and grabs the statistics and basic text data associated with each individual video.
The output is a list of dictionaries, perfect for conversion into a pandas DataFrame.
def youtube_search_list(q, max_results=10):
# Call the search.list method to retrieve results matching the specified
# query term.
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
developerKey=DEVELOPER_KEY)
# Call the search.list method to retrieve results matching the specified
# query term.
search_response = youtube.search().list(
q=q,
part='id,snippet',
maxResults=max_results,
order='viewCount'
).execute()
return search_response
def youtube_search_video(q='spinners', max_results=10):
max_results = max_results
order = "viewCount"
token = None
location = None
location_radius = None
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
developerKey=DEVELOPER_KEY)
q=q
#Return list of matching records up to max_search
search_result = youtube_search_list(q, max_results)
videos_list = []
for search_result in search_result.get("items", []):
if search_result["id"]["kind"] == 'youtube#video':
temp_dict_ = {}
#Available from initial search
temp_dict_['title'] = search_result['snippet']['title']
temp_dict_['vidId'] = search_result['id']['videoId']
#Secondary call to find statistics results for individual video
response = youtube.videos().list(
part='statistics, snippet',
id=search_result['id']['videoId']
).execute()
response_statistics = response['items'][0]['statistics']
response_snippet = response['items'][0]['snippet']
snippet_list = ['publishedAt','channelId', 'description',
'channelTitle', 'tags', 'categoryId',
'liveBroadcastContent', 'defaultLanguage', ]
for val in snippet_list:
try:
temp_dict_[val] = response_snippet[val]
except:
#Not stored if not present
temp_dict_[val] = 'xxNoneFoundxx'
stats_list = ['favoriteCount', 'viewCount', 'likeCount',
'dislikeCount', 'commentCount']
for val in stats_list:
try:
temp_dict_[val] = response_statistics[val]
except:
#Not stored if not present
temp_dict_[val] = 'xxNoneFoundxx'
#add back to main list
videos_list.append(temp_dict_)
return videos_list
this code will help you a ton, i was struggling with this for a long time, just provide the API key and the youtube channel name and the channel id in the search list
from googleapiclient.discovery import build
DEVELOPER_KEY = "paste your API key here"
YOUTUBE_API_SERVICE_NAME = "youtube"
YOUTUBE_API_VERSION = "v3"
title = []
channelId = []
channelTitle = []
categoryId = []
videoId = []
viewCount = []
likeCount = []
dislikeCount = []
commentCount = []
favoriteCount = []
category = []
tags = []
videos = []
tags = []
max_search = 50
order = "relevance"
token = None
location = None
location_radius = None
youtube = build(YOUTUBE_API_SERVICE_NAME, YOUTUBE_API_VERSION,
developerKey=DEVELOPER_KEY)
search_result = youtube.search().list(q="put the channel name here", type="video",
pageToken=token, order=order, part="id,snippet",
maxResults=max_search, location=location,
locationRadius=location_radius, channelId='put the
channel ID here').execute() # this line is to get the videos of the channel by the
name of it
for search_result in search_result.get("items", []):
if search_result["id"]["kind"] == 'youtube#video':
title.append(search_result['snippet']['title']) # the title of the video
videoId.append(search_result['id']['videoId']) # the ID of the video
response = youtube.videos().list(part='statistics, snippet',
id=search_result['id'][
'videoId']).execute() # this is the other request because the statistics and
snippet require this because of the API
channelId.append(response['items'][0]['snippet']['channelId']) # channel ID,
which is constant here
channelTitle.append(response['items'][0]['snippet']['channelTitle']) # channel
title, also constant
categoryId.append(response['items'][0]['snippet']['categoryId']) # stores
the categories of the videos
favoriteCount.append(response['items'][0]['statistics']['favoriteCount']) #
stores the favourite count of the videos
viewCount.append(response['items'][0]['statistics']['viewCount']) #
stores the view counts
"""
the likes and dislikes had a bug all along, which required the if else instead of
just behaving like the viewCount"""
if 'likeCount' in response['items'][0]['statistics'].keys(): # checks
for likes count then restores it, if no likes stores 0
likeCount.append(response['items'][0]['statistics']['likeCount'])
else:
likeCount.append('0')
if 'dislikeCount' in response['items'][0]['statistics'].keys(): # checks for dislikes count then stores it, if no dislikes found returns 0
dislikeCount.append(response['items'][0]['statistics']['dislikeCount'])
else:
likeCount.append('0')
if 'commentCount' in response['items'][0]['statistics'].keys(): # checks for comment count then stores it, if no comment found stores 0
commentCount.append(response['items'][0]['statistics']['commentCount'])
else:
commentCount.append('0')
if 'tags' in response['items'][0]['snippet'].keys(): # checks for tags count then stores it, if none found stores 0
tags.append(response['items'][0]['snippet']['tags'])
else:
tags.append('0')
youtube_dict = {
'tags': tags,
'channelId': channelId,
'channelTitle': channelTitle,
'categoryId': categoryId,
'title': title,
'videoId': videoId,
'viewCount': viewCount,
'likeCount': likeCount,
'dislikeCount': dislikeCount,
'commentCount': commentCount,
'favoriteCount': favoriteCount
}
for x in youtube_dict:
print(x)
for y in youtube_dict[x]:
print(y)
please re indent the code because the site ruined the indentation of python to make the code in the code section not in the words section. good luck