How get info about few posts on facebook? - python

I need to fetch information about likes, comments and etc. from only one post object and here's the request code I send.
Example of my requests:
class StatsSN:
def init(self, fb_post_id, fb_token):
self.fb_post_id = fb_post_id
self.fb_token = fb_token
def req_stats(self, url_method):
req = requests.get(url_method)
if req.status_code != 200:
# return req.json().get('error')
# return 'error'
log.info('FB_Statistics: %s' % req.json())
return -1
return req.json().get('summary').get('total_count')
def fb_likes(self):
url_method = fb_api_url + '%s/likes?summary=true&access_token=%s' % (self.fb_post_id, self.fb_token)
return self.req_stats(url_method)
def fb_reactions(self):
url_method = fb_api_url + '%s/reactions?summary=total_count&access_token=%s' % (self.fb_post_id, self.fb_token)
return self.req_stats(url_method)
def fb_comments(self):
url_method = fb_api_url + '%s/comments?summary=true&access_token=%s' % (self.fb_post_id, self.fb_token)
return self.req_stats(url_method)
def fb_sharedposts(self):
url_method = fb_api_url + '%s/sharedposts?access_token=%s' % (self.fb_post_id, self.fb_token)
req = requests.get(url_method)
if req.status_code != 200:
log.info('FB_Statistics: %s' % req.json())
return -1
return len(req.json().get('data'))
def fb_stats(self):
fb_likes, fb_reactions, fb_comments, fb_sharedposts = self.fb_likes(), self.fb_reactions(), self.fb_comments(), \
self.fb_sharedposts()
return int(fb_likes), int(fb_reactions), int(fb_comments), int(fb_sharedposts)
Is there a method in the Graph API to get info about few posts in one request?

You can achieve it by sending a batch request; If you only need public data, a normal page token is good enough. However if you need private information, you will need a specific page token of the page post you want to get the metrics of.
As the metrics you are referring to are public, you should be able to send a GET request with following syntax:
https://graph.facebook.com/v2.12/?fields=id,comments.limit(0).summary(true),shares,reactions.limit(0).summary(true)&ids=STATUS_ID1,STATUS_ID2,STATUS_ID3,...,STATUS_ID50&access_token=PAGE_TOKEN
You can request up to 50 status id's in one call.
limit(0).summary(true)
This part you need to add with comments and reactions as it is the best practice to retrieve the total amount of comments/reactions.

Related

get parameters in a get request in django rest framework?

I want to get the parameters sent to my rest api
what I want is to obtain the parameters that to use them consume another api and return the response of the third party api
but in name and comic i get None
http://127.0.0.1:8000/searchComics/
{name:"3-D Man","comics":12}
this is my view
class MarvelApi(APIView):
def get(self, request):
private_key = "88958f2d87bd2c0c2fa07b7ea654bcdf9f0389b3"
public_key = "8d415ffcc9add56b0a47c0a7c851afc3"
ts = 1
md5_hash = "46ecbbd63108b0561b8778a57823bd34"
query_params = self.request.query_params
name = query_params.get('kword', None)
comic = query_params.get('comic', None)
end_point = f"https://gateway.marvel.com:443/v1/public/characters?ts={ts}&apikey={public_key}&hash={md5_hash}&name={name}&comic={comic}"
response = requests.get(end_point)
response_json = json.loads(response.text)
return Response(status=status.HTTP_200_OK, data=response_json)
I think the problem is these two lines
name = query_params.get('kword', None)
comic = query_params.get('comic', None)
that do not capture the values ​​correctly, do you know how to solve it?
You wanted to get them from GET method, but instead you gave a dictionary, so I guess you sent it via POST. Instead of posting dictionary you should go with url:
http://127.0.0.1:8000/searchComics/?name=3-D+Man&comic=12
And you had probably a typo. You had plural "comics" in dictionary and you seek for "comic" singular.
And if you want to have data with POST method, just change def get(...) to def post(...).

Instancemethod object is not iterable (AirPi) (Python)

I got ERROR:Exception during output: 'instancemethod' object is not iterable when debugging this AirPi code from https://github.com/haydnw/AirPi/blob/master/outputs/ubidots.py
This suppose to upload my sensor data to the Ubidots server.
*I'd put my correct token and variable ID inside the configuration file for this AirPi.
requiredSpecificParams = ["token"]
optionalSpecificParams = ["showcost",
"ID-BMP085-temp",
"ID-BMP085-pres",
"ID-DHT22-hum",
"ID-DHT22-temp",
"ID-LDR",
"ID-TGS2600",
"ID-MiCS-2710",
"ID-MiCS-5525",
"ID-Microphone",
"ID-Raingauge"
]
def __init__(self, config):
super(Ubidots, self).__init__(config)
self.token = self.params["token"]
if "showcost" in self.params:
self.showcost = self.params["showcost"]
else:
self.showcost = False
self.ubivariables = {}
for key, value in self.params.iteritems():
if key[:3] == "ID-":
if value:
self.ubivariables[key[3:]] = value
def output_data(self, datapoints, dummy):
"""Output data.
Output data in the format stipulated by the plugin. Calibration
is carried out first if required.
Because this particular plugin (ubidots) does not show time, the
third argument (normally called 'sampletime') is called 'dummy'
to facilitate compliance with pylint.
Args:
self: self.
datapoints: A dict containing the data to be output.
dummy: datetime representing the time the sample was taken.
Returns:
boolean True if data successfully output to Ubidots; False if
not
"""
if self.params["calibration"]:
datapoints = self.cal.calibrate(datapoints)
payload = []
for point in datapoints:
for ubivariablename, ubivariableid in self.ubivariables.iteritems():
if point["sensor"] == ubivariablename:
if point["value"] is not None:
thisvalue = {}
thisvalue["variable"] = ubivariableid
thisvalue["value"] = point["value"]
payload.append(thisvalue)
break
headers = {'Accept': 'application/json; indent=4', 'Content-Type': 'application/json', 'X-Auth-Token': self.token}
url = "http://things.ubidots.com/api/v1.6/collections/values"
req = None
cost = 0
try:
req = requests.post(url, data=json.dumps(payload), headers=headers)
except Exception, e:
print("ERROR: Failed to contact the Ubidots service.")
print("ERROR: " + str(e))
return False
for response in req.json:
if response["status_code"] is not 201:
print("ERROR: Ubidots responded with an error for one of the values.")
return False
else:
cost += 1
if self.showcost:
print("Ubidots upload cost " + str(cost) + " dots.")
return True
for response in req.json:
According to the documentation, json is a method and must be called, so this should be:
for response in req.json():
In the future it is helpful to include just as much of your code as is necessary to reproduce the problem, and to include the complete error message with traceback.

Python API Client Rerun function if run unsuccessfully

Python Requests API client has a function that needs to re execute if run unsuccessfully.
Kitten(BaseClient):
def create(self, **params):
uri = self.BASE_URL
data = dict(**(params or {}))
r = self.client.post(uri, data=json.dumps(data))
return r
If ran with
api = Kitten()
data = {"email": "bill#dow.com", "currency": "USD", "country": "US" }
r = api.create(**data)
The issue is whenever you run it, the first time it always returns back the request as GET, even when it it POST. The first time the post is sent, it returns back GET list of entries.
The later requests, second and later, api.create(**data) return back new entries created like they should be.
There is a status_code for get and post
# GET
r.status_code == 200
# POST
r.status_code == 201
What would be better Python way to re execute when status_code is 200, till a valid 201 is returned.
If you know for sure that the 2nd post will always return your expected value, you can use a ternary operator to perform the check a second time:
Kitten(BaseClient):
def create(self, **params):
uri = self.BASE_URL
data = dict(**(params or {}))
r = self._get_response(uri, data)
return r if r.status_code == 201 else self._get_response(uri, data)
def _get_response(uri, data):
return self.client.post(uri, data=json.dumps(data)
Otherwise you can put it in a while loop where the condition is that the status code == 201.

python with Quickbooks Online API v3

I need some help implementing a python app that accesses the Quickbooks API. I have successfully written several apps that use APIs, but once we get into the OAuth world, I get a bit lost.
At any rate, I found the quickbooks-python wrapper here:
https://github.com/troolee/quickbooks-python
but there are zero examples of working code showing how to implement properly. I imagine that a more experienced python programmer could figure out how to make this work without any instructions, but it seems like I'm missing the basics.
If I could get it connected, I could probably get it to work from there...
It seems like the documentation on github jumps around and for a more experienced programmer, would probably make perfect sense. But I'm just not following...
from quickbooks import *
consumerKey = "fromApiConsole"
consumerSecret = "fromApiConsole"
callbackUrl = "https://quickbooks.api.intuit.com/v3"
qbObject = QuickBooks(
consumer_key = consumerKey,
consumer_secret = consumerSecret,
callback_url = callbackUrl
)
authorize_url = qbObject.get_authorize_url() # will create a service, and further set up the qbObject.
oauth_token = request.GET['oauth_token']
oauth_verifier = request.GET['oauth_verifier']
realm_id = request.GET['realmId']
session = qbObject.get_access_tokens(oauth_verifier)
# say you want access to the reports
reportType = "ProfitAndLoss"
url = "https://quickbooks.api.intuit.com/v3/company/asdfasdfas/"
url += "reports/%s" % reportType
r = session.request( #This is just a Rauth request
"POST",
url,
header_auth = True,
realm = realm_id,
params={"format":"json"}
)
qb = QuickBooks(
consumer_key = consumerKey,
consumer_secret = consumerSecret,
access_token = qbtoken.access_token, # the stored token
access_token_secret = qbtoken.access_token_secret, # the stored secret
company_id = qbtoken.realm_id #the stored realm_id
)
qbText = str(qb.query_objects(business_object, params, query_tail))
print qbText
I am pretty sure that I am:
importing the wrong modules/classes
missing huge pieces of code to "glue together" the samples found on github
not using django here and i know the request class above is in django, but i'd really like to just make this work as a python script without using django
not getting the token/identifier/realmId from the initial authorize_url function. it prints on the screen, but i'm not sure how to grab it...
The end goal here is really just to connect and get a P&L statement from Quickbooks Online. If I can get that far, I am sure I can get the rest of what I need out of the API. I don't really need to CHANGE anything, I'm just looking to include data from the reports into some dashboards.
* UPDATE *
okay, i figured out how to get it to connect, but i'm not sure how to get to the reports.
the answer was this, which was on the prior API page:
Accessing the API
Once you've gotten a hold of your QuickBooks access tokens, you can create a QB object:
qb = QuickBooks(consumer_key = QB_OAUTH_CONSUMER_KEY,
consumer_secret = QB_OAUTH_CONSUMER_SECRET,
access_token = QB_ACCESS_TOKEN,
access_token_secret = QB_ACCESS_TOKEN_SECRET,
company_id = QB_REALM_ID
)
still trying to get the basic reports...
Okay, so here's how to make this work. I'm focused on the reports, so here's how you can get reports from Quickbooks Online API using Python:
1) Go to https://github.com/finoptimal-dev/quickbooks-python and download the code
2) Make sure you have rauth installed. If you are on AWS/EC2, simply:
sudo yum install rauth
3) Edit the quickbooks2.py file and add the following to the END:
qb = QuickBooks(consumer_key = QB_OAUTH_CONSUMER_KEY,
consumer_secret = QB_OAUTH_CONSUMER_SECRET,
access_token = QB_ACCESS_TOKEN,
access_token_secret = QB_ACCESS_TOKEN_SECRET,
company_id = QB_REALM_ID
)
4) Setup a sandbox application on the Quickbooks site here: https://developer.intuit.com/v2/ui#/app/startcreate (you will have to create a developer account if you don't already have one)
5) Once setup, you can go to the "Keys" tab of the App and grab the App Token, OAuth Consumer Key and OAuth Consumer Secret.
6) Go to the Intuit Developer Playground at https://appcenter.intuit.com/Playground/OAuth/IA and use the info from step #5 to obtain the Access Token and Access Token Secret.
7) Change the variables in Step #3 to the correct values. For QB_REALM_ID, this is the Company ID. You can get this in the sandbox by logging into https://developer.intuit.com/v2/ui#/sandbox and looking for Company ID.
7) add the following code below the code from step #3 above
print qb.get_report('ProfitAndLoss','summarize_column_by=Month&start_date=2014-01-01&end_date=2014-12-31')
I use the above dates b/c the Quickbooks Sandbox company has no Income/Expense data in 2015, so you have to pick dates in 2014.
8) IMPORTANT: To use with the Quickbooks Sandbox for reporting purposes, you need to change the get_report() function to use the base_url_v3 instead of being hard-coded to the production URL.
Look for a row in the get_report() function that looks like this:
url = "https://quickbooks.api.intuit.com/v3/company/%s/" % \
and change it to this:
url = self.base_url_v3 + "/company/%s/" % \
9) Now you can change base_url_v3 all the way at the top to this:
base_url_v3 = "https://sandbox-quickbooks.api.intuit.com/v3"
10) And now you should now be able to run:
python quickbooks2.py
You should see a bunch of JSON data from the Quickbooks Sandbox company.
11) You can explore a bit to test out the appropriate URLs here: https://developer.intuit.com/apiexplorer?apiname=V3QBO#Reports
12) The report reference is here: https://developer.intuit.com/docs/0100_accounting/0400_references/reports and this shows you which parameters you can use. To test parameters in the Explorer, you enter them in the "Request Body" section.
I struggled with this for a while and finally figured it out. Hope this helps someone else.
I do not have much experience with Python but someone had shared this code with me for oauth earlier.If you have additional questions on the code, I will not be able to answer them.
NOTE: The below code also makes calls to V2 QBO apis. Please do not use that part as it is deprecated.
See if it helps-
Import Python
from rauth import OAuth1Session, OAuth1Service
import xml.etree.ElementTree as ET
import xmltodict
class QuickBooks():
"""A wrapper class around Python's Rauth module for Quickbooks the API"""
access_token = ''
access_token_secret = ''
consumer_key = ''
consumer_secret = ''
company_id = 0
callback_url = ''
session = None
base_url_v3 = "https://quickbooks.api.intuit.com/v3"
base_url_v2 = "https://qbo.intuit.com/qbo1"
request_token_url = "https://oauth.intuit.com/oauth/v1/get_request_token"
access_token_url = "https://oauth.intuit.com/oauth/v1/get_access_token"
authorize_url = "https://appcenter.intuit.com/Connect/Begin"
# Things needed for authentication
qbService = None
request_token = ''
request_token_secret = ''
def __init__(self, **args):
if 'consumer_key' in args:
self.consumer_key = args['consumer_key']
if 'consumer_secret' in args:
self.consumer_secret = args['consumer_secret']
if 'access_token' in args:
self.access_token = args['access_token']
if 'access_token_secret' in args:
self.access_token_secret = args['access_token_secret']
if 'company_id' in args:
self.company_id = args['company_id']
if 'callback_url' in args:
self.callback_url = args['callback_url']
def get_authorize_url(self):
"""Returns the Authorize URL as returned by QB,
and specified by OAuth 1.0a.
:return URI:
"""
self.qbService = OAuth1Service(
name = None,
consumer_key = self.consumer_key,
consumer_secret = self.consumer_secret,
request_token_url = self.request_token_url,
access_token_url = self.access_token_url,
authorize_url = self.authorize_url,
base_url = None
)
self.request_token, self.request_token_secret = self.qbService.get_request_token(
params={'oauth_callback':self.callback_url}
)
return self.qbService.get_authorize_url(self.request_token)
def get_access_tokens(self, oauth_verifier):
"""Wrapper around get_auth_session, returns session, and sets
access_token and access_token_secret on the QB Object.
:param oauth_verifier: the oauth_verifier as specified by OAuth 1.0a
"""
session = self.qbService.get_auth_session(
self.request_token,
self.request_token_secret,
data={'oauth_verifier': oauth_verifier})
self.access_token = session.access_token
self.access_token_secret = session.access_token_secret
return session
def create_session(self):
if self.consumer_secret and self.consumer_key and self.access_token_secret and self.access_token:
# print "hi"
session = OAuth1Session(self.consumer_key,
self.consumer_secret,
self.access_token,
self.access_token_secret,
)
# print session
self.session = session
else:
pass
#TODO: raise an error
return self.session
def keep_trying(self, r_type, url, header_auth, realm, payload=''):
if self.session != None:
session = self.session
else:
session = self.create_session()
self.session = session
trying = True
tries = 0
while trying:
print url
tries += 1
if "v2" in url:
r = session.request(r_type, url, header_auth, realm, data=payload)
r_dict = xmltodict.parse(r.text)
# print "DICT", r_dict
if "FaultInfo" not in r_dict or tries > 4:
trying = False
else:
# url = "https://qb.sbfinance.intuit.com/v3/company/184010684/query?query=SELECT * FROM JournalEntry"
# url = "https://quickbooks.api.intuit.com/v3/company/184010684/journalentry/24772"
# url = "https://quickbooks.api.intuit.com/v3/company/184010684/query?query='SELECT+*+FROM+JournalEntry'"
# url = "https://qb.sbfinance.intuit.com/v3/company/184010684/query?query=SELECT%20%2A%20FROM%20JournalEntry&"
print url, r_type
headers = {'Accept': 'application/json'}
r = session.request(r_type, url, header_auth, realm, headers = headers)
# r.headers
print "\n\n INITIAL TEXT \n\n", r.text
print "request headers:", r.request.headers
print "request URL:", r.request.url
print "response headers:", r.headers
r_dict = r.text
if "Fault" not in r_dict or tries > 4:
trying = False
r_dict = []
return r_dict
def fetch_customer(self, pk):
if pk:
url = self.base_url_v2 + "/resource/customer/v2/%s/%s" % ( self.company_id, pk)
r_dict = self.keep_trying("GET", url, True, self.company_id)
return r_dict['Customer']
def fetch_customers(self, all=False, page_num=0, limit=10):
if self.session != None:
session = self.session
else:
session = self.create_session()
self.session = session
# We use v2 of the API, because what the fuck, v3.
url = self.base_url_v2
url += "/resource/customers/v2/%s" % (self.company_id)
customers = []
if all:
counter = 1
more = True
while more:
payload = {
"ResultsPerPage":30,
"PageNum":counter,
}
trying = True
# Because the QB API is so iffy, let's try until we get an non-error
# Rewrite this to use same code as above.
while trying:
r = session.request("POST", url, header_auth = True, data = payload, realm = self.company_id)
root = ET.fromstring(r.text)
if root[1].tag != "{http://www.intuit.com/sb/cdm/baseexceptionmodel/xsd}ErrorCode":
trying = False
else:
print "Failed"
session.close()
qb_name = "{http://www.intuit.com/sb/cdm/v2}"
for child in root:
# print child.tag, child.text
if child.tag == "{http://www.intuit.com/sb/cdm/qbo}Count":
if int(child.text) < 30:
more = False
print "Found all customers"
if child.tag == "{http://www.intuit.com/sb/cdm/qbo}CdmCollections":
for customer in child:
customers += [xmltodict.parse(ET.tostring(customer))]
counter += 1
# more = False
# print more
else:
payload = {
"ResultsPerPage":str(limit),
"PageNum":str(page_num),
}
r = session.request("POST", url, header_auth = True, data = payload, realm = self.company_id)
root = ET.fromstring(r.text)
#TODO: parse for all customers
return customers
def fetch_sales_term(self, pk):
if pk:
url = self.base_url_v2 + "/resource/sales-term/v2/%s/%s" % ( self.company_id, pk)
r_dict = self.keep_trying("GET", url, True, self.company_id)
return r_dict
def fetch_invoices(self, **args):
if "query" in args:
payload = ""
if "customer" in args['query']:
payload = {
"Filter":"CustomerId :Equals: %s" % (args['query']['customer'])
}
# while more:
url = self.base_url_v2 + "/resource/invoices/v2/%s/" % (self.company_id)
r_dict = self.keep_trying("POST", url, True, self.company_id, payload)
invoices = r_dict['qbo:SearchResults']['qbo:CdmCollections']['Invoice']
return invoices
elif "pk" in args:
# TODO: Not tested
url = self.base_url_v2 + "/resource/invoice/v2/%s/%s" % ( self.company_id, args['pk'])
r_dict = self.keep_trying("GET", url, True, self.company_id)
return r_dict
else:
url = self.base_url_v2 + "/resource/invoices/v2/%s/" % (self.company_id)
r_dict = self.keep_trying("POST", url, True, self.company_id, payload)
return "BLAH"
def fetch_journal_entries(self, **args):
""" Because of the beautiful way that journal entries are organized
with QB, you're still going to have to filter these results for the
actual entity you're interested in. Luckily it only returns the entries
that are relevant to your search
:param query: a dictionary that includes 'customer', and the QB id of the
customer
"""
if "query" in args:
payload = {}
more = True
counter = 1
journal_entries = []
if "customer" in args['query']:
payload = {
"Filter":"CustomerId :Equals: %s" % (args['query']['customer'])
}
# payload = {
# "query":"SELECT * FROM JournalEntry",
# }
while more:
payload["ResultsPerPage"] = 30
payload["PageNum"] = counter
# url = self.base_url_v2 + "/resource/journal-entries/v2/%s/" % (self.company_id)
# url = self.base_url_v3 + "/company/%s/query" % (self.company_id)
url = "https://qb.sbfinance.intuit.com/v3/company/184010684/query?query=SELECT%20%2A%20FROM%20JournalEntry&"
r_dict = self.keep_trying("GET", url, True, self.company_id, payload)
more = False
# print r_dict['qbo:SearchResults']['qbo:Count']
counter = counter + 1
# if int(r_dict['qbo:SearchResults']['qbo:Count']) < 30:
# more = False
# journal_entry_set = r_dict['qbo:SearchResults']['qbo:CdmCollections']['JournalEntry']
# journal_entries += [journal_entry_set]
return []
# return r_dict['qbo:SearchResults']['qbo:CdmCollections']['JournalEntry']
elif "pk" in args:
# TODO: Not Tested
url = self.base_url_v2 + "/resource/journal-entry/v2/%s/%s" % ( self.company_id, args['pk'])
r_dict = self.keep_trying("GET", url, True, self.company_id)
return r_dict
else:
url = self.base_url_v2 + "/resource/journal-entries/v2/%s/" % (self.company_id)
r_dict = self.keep_trying("POST", url, True, self.company_id)
print r_dict
return "BLAH"

How can I implement dynamic routing in Python?

I'm attempting to implement dynamic routing for a web framework. At the moment, the goal is to pass arguments into a function by way of the url. So, if user offers a url of "/page/23", then the route function will extract the "23" which will then be used as a parameter for the page function. I am getting a "keyerror", however.
import re
routing_table = {}
url = "/page/23"
def route(url, func):
key = url
key = re.findall(r"(.+?)/<[a-zA-Z_][a-zA-Z0-9_]*>", url)
if key:
params = re.findall(r"<([a-zA-Z_][a-zA-Z0-9_]*)>", url)
routing_table[key[0]] = [params, func]
else:
routing_table[url] = func
def find_path(url):
if url in routing_table:
return routing_table[url]
else:
return None
def page(page_id):
return "this is page %d" % page_id
route("/page/<page_id>", page)
print(routing_table[url])
When you called route, you used a url equal to "/page/<page_id>", but in the last line, url is a global variable equal to "/page/23".
It looks like there are other problems: replace your last line with
print(routing_table)
to see what you're doing.

Categories