Post a photo in FB with GraphAPI in Python - python

Right now my job is advertise different kinds of business.
In order to do that i need to post in multiple facebook groups different products but that eats pretty much all my time so i'm trying to develop my own post-bot so i can post whatever i want in the moment in all the specific local facebook groups immediately.
I can post text in the feed, but can't make the code post a picture with text.
I get this error:
Traceback (most recent call last):
File "C:\Users\Ventas\Desktop\Post2.py", line 31, in
graph.put_object(parent_object=group_id, connection_name='photos', caption=titulo, message=mensaje, source=foto) File
"C:\Python27\lib\site-packages\facebook__init__.py", line 144, in
put_object
method="POST") File "C:\Python27\lib\site-packages\facebook__init__.py", line 272, in
request
raise GraphAPIError(result) GraphAPIError: (#324) Requires upload file
I don't know what i'm doing wrong, this is my code:
#SETUP Photo with file selection dialog
Tkinter.Tk().withdraw()
dir = tkFileDialog.askopenfilename()
photo = open(dir, "rb").read()
#POST IN GROUPS
for group_id in groups:
print("Posting to " + 'https://www.facebook.com/groups/' + str(group_id))
graph.put_object(parent_object=group_id, connection_name='photos', caption=titulo, message=mensaje, source=photo)

Ok, i tried selenium, something that a guy on facebook recommended me, but it did not worked, so i went back to python.
I was playing around with the api, but the documentation was not very clear in how to post in a group specifically.
So i started surfing the most deep part in google and found THIS
It made me reach to the conclusion of the code, the freakin' solution! :D (OMG FINALLY) i've been working on this thing like 4 days already.
I just changed this:
graph.put_object(parent_object=group_id, connection_name='photos', caption=titulo, message=mensaje, source=photo)
To this:
graph.put_photo(image=photo, message=mensaje, album_path=group_id + "/photos")
Also i noticed that the original documentation says that the value "album_path" should be:
album_path=group_id + "/pictures"
But thats ONLY and STRICTLY for pages.
It seems that for groups is:
album_path=group_id + "/photos"
Thank you to anyone who bothered to at least read my question, and very special thanks to the users "Jérémy de Gail" and "Amit Singh" from facebook, since no one bothered to even try to help me.
This code is very important for my job.
Hope my own answer may help someone in the future.
Regards to everyone! :D

Try to put the picture in the same file where you have your .py script.
Then, do:
photo = "nameofyourpic.jpg"
Instead of:
photo = open(dir, "rb").read()

As of the new API release, you can no longer upload images through a local path but rather a relative URL (Image stored on server).
graph.put_object(parent_object=group_id, connection_name='photos', caption=titulo, message=mensaje, source="https://1.bp.blogspot.com/-VqCH72pVnok/X-WgDpD5jSI/AAAAAAAA20E/pLCoCXR_7tsme8etcjYAOJhNa9GdPh4ewCLcBGAsYHQ/w640-h428/iherb_holiday.png")

Related

Only 1 KB of file is downloading, instead of the whole thing in Python

I've attempted to use urllib, requests, and wget. All three don't work.
I'm trying to download a 300KB .npz file from a URL. When I download the file with wget.download(), urllib.request.urlretrieve(), or with requests, an error is not thrown. The .npz file downloads. However, this .npz file is not 300KB. The file size is only 1 KB. Also, the file is unreadable - when I use np.load(), the error OSError: Failed to interpret file 'x.npz' as a pickle shows up.
I am also certain that the URL is valid. When I download the file with a browser, it is correctly read by np.load() and has the right file size.
Thank you very much for the help.
Edit 1:
The full code was requested. This was the code:
loadfrom = "http://example.com/dist/x.npz"
savedir = "x.npz"
wget.download(loadfrom, savedir)
data = np.load(savedir)
I've also used variants with urllib:
loadfrom = "http://example.com/dist/x.npz"
savedir = "x.npz"
urllib.request.urlretrieve(loadfrom, savedir)
data = np.load(savedir)
and requests:
loadfrom = "http://example.com/dist/x.npz"
savedir = "x.npz"
r = requests.get(loadfrom).content
with open("x.npz",'wb') as f:
f.write(r)
data = np.load(savedir)
They all produce the same result, with the aforementioned conditions.
Kindly show the full code and the exact lines you use to download the file. Remember you need to use
r=requests.get("direct_URL_of_your_file.npz").content
with open("local_file.npz",'wb') as f:
f.write(r)
Also make sure the URL is a direct download link.
The issue was that the server needed javascript to run as a security precaution. So, when I send the request, all I got was html with "This Site Requres Javascript to Work". I found out that there was a __test cookie that needed to be passed during the request.
This answer explains it fully. This video may also be helpful.

How to use Python to pipe a .htm file to a website

I have a file, gather.htm which is a valid HTML file with header/body and forms. If I double click the file on the Desktop, it properly opens in a web browser, auto-submits the form data (via <SCRIPT LANGUAGE="Javascript">document.forms[2].submit();</SCRIPT>) and the page refreshes with the requested data.
I want to be able to have Python make a requests.post(url) call using gather.htm. However, my research and my trail-and-error has provided no solution.
How is this accomplished?
I've tried things along these lines (based on examples found on the web). I suspect I'm missing something simple here!
myUrl = 'www.somewhere.com'
filename='/Users/John/Desktop/gather.htm'
f = open (filename)
r = requests.post(url=myUrl, data = {'title':'test_file'}, files = {'file':f})
print r.status_code
print r.text
And:
htmfile = 'file:///Users/John/Desktop/gather.htm'
files = {'file':open('gather.htm')}
webbrowser.open(url,new=2)
response = requests.post(url)
print response.text
Note that in the 2nd example above, the webbrowser.open() call works correctly but the requests.post does not.
It appears that everything I tried failed in the same way - the URL is opened and the page returns default data. It appears the website never receives the gather.htm file.
Since your request is returning 200 OK, there is nothing wrong getting your post request to the server. It's hard to give you an exact answer, but the problem lies with how the server is handling the request. Either your post request is being formatted in a way that the server doesn't recognise, or the server hasn't been set up to deal with them at all. If you're managing the website yourself, some additional details would help.
Just as a final check, try the following:
r = requests.post(url=myUrl, data={'title':'test_file', 'file':f})

Post image to facebook via python and graphapi

Hoping to get some help with error I am getting. I am able to authenticate and post text to a users wall (so I am thinking that I am properly authenticated).
The code I am using is as follows:
self.client = GraphAPI(ACCESS_TOKEN)
self.client.put_photo(open("test.jpg"), "test post from app - please ignore")
I get the following error:
Traceback (most recent call last):
File "J:\Projects\python Code\pyhton test programs\upload posts to facebook v3.py", line 69, in OnFacebookPublishButton
self.client.put_photo(open("test.jpg"), "test post from app - please ignore")
File "C:\Python27\lib\site-packages\facebook.py", line 231, in put_photo
raise GraphAPIError(response)
facebook.GraphAPIError: Your photos couldn't be uploaded. Photos should be saved as JPG, PNG, GIF, BMP or TIFF files.
I have verified using the windows explore, ACDSee, Photoshop, Paint and Faststone, that the jpg are valid.
Try this:
self.client = GraphAPI(ACCESS_TOKEN)
with open("test.jpg","rb") as image:
self.client.put_photo(image, "test post from app - please ignore")
the open function takes several parameters one of which is the mode in which it will open, your error is most likely that you did not specify the open mode after the file name.
Another important thing is that when you open a file, you also need to close it, so your code falters in the fact that it doesn't seem to include a .close() function call.
In my suggestion I open the image as read (binary) mode and use the with statement to avoid the closing statement.
I suggest you take some time to learn about the open function by reading the official docs
https://docs.python.org/2/library/functions.html#open

send data from blobstore as email attachment in GAE

Why isn't the code below working? The email is received, and the file comes through with the correct filename (it's a .png file). But when I try to open the file, it doesn't open correctly (Windows Gallery reports that it can't open this photo or video and that the file may be unsupported, damaged or corrupted).
When I download the file using a subclass of blobstore_handlers.BlobstoreDownloadHandler (basically the exact handler from the GAE docs), and the same blob key, everything works fine and Windows reads the image.
One more bit of info - the binary files from the download and the email appear very similar, but have a slightly different length.
Anyone got any ideas on how I can get email attachments sending from GAE blobstore? There are similar questions on S/O, suggesting other people have had this issue, but there don't appear to be any conclusions.
from google.appengine.api import mail
from google.appengine.ext import blobstore
def send_forum_post_notification():
blob_reader = blobstore.BlobReader('my_blobstore_key')
blob_info = blobstore.BlobInfo.get('my_blobstore_key')
value = blob_reader.read()
mail.send_mail(
sender='my.email#address.com',
to='my.email#address.com',
subject='this is the subject',
body='hi',
reply_to='my.email#address.com',
attachments=[(blob_info.filename, value)]
)
send_forum_post_notification()
I do not understand why you use a tuple for the attachment. I use :
message = mail.EmailMessage(sender = ......
message.attachments = [blob_info.filename,blob_reader.read()]
I found that this code doesn't work on dev_appserver but does work when pushed to production.
I ran into a similar problem using the blobstore on a Python Google App Engine application. My application handles PDF files instead of images, but I was also seeing a "the file may be unsupported, damaged or corrupted" error using code similar to your code shown above.
Try approaching the problem this way: Call open() on the BlobInfo object before reading the binary stream. Replace this line:
value = blob_reader.read()
... with these two lines:
bstream = blob_info.open()
value = bstream.read()
Then you can remove this line, too:
blob_reader = blobstore.BlobReader('my_blobstore_key')
... since bstream above will be of type BlobReader.
Relevant documentation from Google is located here:
https://cloud.google.com/appengine/docs/python/blobstore/blobinfoclass#BlobInfo_filename

App Engine - Save response from an API in the data store as file (blob)

I'm banging my head against the wall with this one:
What I want to do is store a file that is returned from an API in the data store as a blob.
Here is the code that I use on my local machine (which of course works due to an existing file system):
client.convertHtml(html, open('html.pdf', 'wb'))
Since I cannot write to a file on App Engine I tried several ways to store the response, without success.
Any hints on how to do this? I was trying to do it with StringIO and managed to store the response but then weren't able to store it as a blob in the data store.
Thanks,
Chris
Found the error. Here is how it looks like right now (simplified).
output = StringIO.StringIO()
try:
client.convertURI("example.com", output)
Report.pdf = db.Blob(output.getvalue())
Report.put()
except pdfcrowd.Error, why:
logging.error('PDF creation failed %s' % why)
I was trying to save the output without calling "getvalue()", that was the problem. Perhaps this is of use to someone in the future :)

Categories

Resources