How I Created a Python Meme Bot for Instagram !!

How I Created a Python Meme Bot for Instagram !!

ยท

8 min read

The Story behind

Most of my time is spent on Instagram and I use it mostly for the memes.

So, some of my friends told me that most of the memes are uploaded to Reddit and later spread to Instagram, and Reddit was the best place to go for funny content but I wasn't a big fan of the Reddit UI and didn't really get used to it.

One day I randomly thought, what if I could start a meme page that gets content from Reddit but without downloading and uploading the images manually and still be the first account to upload those memes on Instagram straight from Reddit?

And, I Built a BOT which uploads memes from some subreddits like r/dankmemes and r/memes and uploads it on my Instagram account - @thiru.bot

How did I do it?

At this stage, I was a beginner and knew few things about python, had some experience building flask apps, had some experience in web scrapping and had huge hunger to build this just to flex my skills with my friends.

Before I started building it I had to visualize what I needed?

  • Reddit API & Basics of web scrapping to get the images and save them.
  • Any Instagram API which lets me upload photos to my account.
  • A server to host this later to make it work 24/7

Friends, When you are a beginner you just google things, mix code from different repositories, add your own code and make it work.

and that's what I did! There were no Instagram Reddit bot but I found a Reddit to twitter project which gave me a clarity of thought in building this.

The Working Instagram API

The Official Instagram API doesn't allow developers to upload photos or videos to post. Most of the other third party APIs also dint work but at last found this pip package.

pip install instabot

Later Tested if this worked by giving my Instagram credentials and uploaded a random photo from my computer.

from instabot import Bot
bot=Bot()
bot.login(username="thiru.jpg",password="followMeOnInstagram")

bot.upload_photo('hey.png',caption=("Test Upload "))

and it worked :)

Next step - Scrapping the latest images from subreddits

Getting Images from Reddit

To get the latest submissions from our subreddits we will be using PRAW API from subreddit. it's pretty simple not to worry.

Setting up Praw API

reddit = praw.Reddit(client_id='',
client_secret='',
username='',
password='',
user_agent='')

Creating an Reddit App

To Fill the above details you need to create an app on Reddit, Just Open https://ssl.reddit.com/prefs/apps/ and click on create app.

praw.PNG

I am here creating an app with the name test app. Client_Id parameter (the one which is below personal use script in the image above), client_secret is the secret key available. For username and password give your Reddit username and password. User Agent can be blank or chrome.

Setting up subreddits to get memes

red='dankmemes'
subreddit = reddit.subreddit(red)
newMemes = subreddit.hot(limit=3)

I choose the subreddit 'dankmemes' and NewMemess Praw Class has all the hottest submissions from the subreddit. You can get any type of submissions (refer to official documentation here )

Validating and Picking only Photos

for submission in new_memes:
    if submission.is_self == True:
        print("Post was text, skipping to next post.")
        continue
    else:
        pass
url = submission.url
time.sleep(waitTime)

You want just photos to upload. So, You need to validate them and choose only the submissions which have photos.

Downloading the images

Before Storing the images from Reddit we check Two Things

  • if the submission is an Video/text or an image using isImageLink(url) Function and it returns the extension name of the image(Eg: jpg,png)
  • If the image was posted before using already_uploaded(id) function so that we don't post the same memes again.

You can check out those functions and full code on my GitHub Repo here also follow me on GitHub.

if isImageLink(url) and not already_uploaded(id):
    try:
        img=requests.get(submission.url)
        filename=str(counter)+'.'+IsImageLink(submission.url)
        filename=os.path.join('images', filename)
        imagefile=open(filename, 'wb')
        imagefile.write(img.content)
        imagefile.close()
        post_ids.append(submission.id) # A list of all submission ids
        log_insta(post_ids)
        photoAlbum.append({'File':filename, 'Title':submission.title})
        #dictionary of all photos
        counter+=1
    except Exception as e:
        print(e)

After checking, You can download the image and save it with the count+ the extension (Eg: 2.png or 3.jpg).

Later you save a list with all the post id.

Remember you had to check if the post was already uploaded. How will it know if it is posted already? Yes, you will be logging the post_id of the image using the function log_insta(post_ids)

def log_insta(post_ids):
    for post_id in post_ids:
        with open(POSTED_CACHE, 'a') as out_file:
            out_file.write(str(post_id) + '\n')

Downloading the images from Imgur

Some Redditors upload photos to Imgur, and to download those images, You will using beautifulSoup and scrape data from those submissions. After you download, the saving part is same as above so I won't be posting the whole code.

elif str(submission.url).lower().startswith('https://imgur.com') or str(submission.url).lower().startswith('http://imgur.com') and counter<max_images:

    try:
        html_page = urllib.request.urlopen(submission.url)
        soup = BeautifulSoup(html_page, 'lxml')
        images = []
        for img in soup.findAll('img'):
        images.append('https:'+img.get('src'))

        img=requests.get(images[0])
        filename=str(counter)+'.'+images[0][-3:]

Downloaded the images, What next?

Now that we have all the 3 images in the photo album Dictionary with the File and Title we can upload it to instagram using our unofficial Instagram API and give credits to the authors,subreddit and also add captionTags.

authors = ''.join(str(e + ', ') for e in authors)
captionTags='#binod #memes #dank'
for photo in photoAlbum:
    img=photo['File']
    captionText=photo['Title']
bot.upload_photo(img,caption=(captionText + '\n' +'Reddit Authors:'+authors+'\n' captionTags))

Later we delete the image we downloaded just not to waste disk space.

for filename in glob(filePath + '/*'):
os.remove(filename)

Now Put all this code together into a single Python File, Run it and Hola, You have now uploaded a meme from Reddit to Instagram from your Python Code In my case, I named the file bot.py, thought of telling you this as this might be useful later in the deployment part.

But the bot.py is run on the local machine and we can't just run this 24/7 on our local machine. Any Fix?

Deployment

To Run The Bot in a server for 24/7 you need to deploy this to cloud. I used Heroku to deploy this Instagram meme bot. Follow this article to set up a Heroku account and know the basics of Heroku. I will soon be writing an article on the same.How to Upload Flask apps to Heroku .

You need 3 files to be created for the deployment of your bot into Heroku .

  • ProcFile
  • Runtime.txt
  • Requirements.txt

Runtime.txt

python-3.7.3

In Runtime.txt you specify what language your code is in.

The ProcFile

web: python3 bot.py
worker: python3 bot.py

Here you will be specifying the python file to be run by the dynos and note that I created two of these just to make sure one of them always stays on and doesn't sleep. You later need to scale them.

Requirements.txt

imageio==2.4.1
praw
requests
urllib3
keyboard
pillow
beautifulsoup4
instabot

Heroku in simple words creates a virtual machine so you need to mention what are the packages you want to install for your bot.py to work.

After Uploading these files into a single folder. It's time to scale your dynos

heroku ps:scale web=1 worker=1

A working meme BOT

thiru.bot.PNG

But yeah , I need to work on the followers count lol.

Problems & Suggestions

  • Instagram Detecting Bots
  • Upload Frequency
  • Heroku Running out of Credits
  • Dynamic Tags

Instagram Detecting Bots

Instagram DOES NOT like Bots.

Initially, when I started this, my bot was detected and banned for 1 day and was not allowed to use any Instagram features like liking, etc for 1 week.

Solution which worked for me

It took me weeks to crack this but the reason why my bot was getting detected is that my posts were only from one subreddit and the authors were mostly same and hashtags as well so every post had somethings similar and with same upload frequency and Instagram started detecting.

With no options left, I had to stop giving credits to authors in the caption and created a list of subreddits and used random function in Python to select one subreddit and stoped using tags which fixed the issue.Upload frequency also matters and I will be speaking about it in the next paragraphs.

Upload Frequency

How many Posts should you upload at a time?

How many hours once should you upload?

The safe bet is 3 posts /hour

Heroku Running out of credits

Heroku gives 550 hours of free dynos when you create an account. I had used all the 550 dynos and all my projects on Heroku had shut down, luckily I gave my credit card information and was able to get an extra 450 hours of dynos, But that won't be sufficient if you want to run this bot forever as 30 days = 1800 hours. I usually was turning off the dynos when I was going to sleep and turning it on when required so worked. This is the solution that worked out for me and just to remind you, this is hosted for completely free of cost so nothing to complain.

Dynamic Tags

So, removing tags helped with not getting banned but I wanted better reach as my account had just 3 followers from weeks so created multiple lists of trending hashtags and wrote a code to choose the hashtags according to the subreddit and its working great.

What Did we learn from this?

  • You Don't need to know everything to start building things. Just the Hunger is enough.
  • The results don't come just in the first iteration. Experiment Fix experiment.
  • You can't get a girlfriend by creating a Meme bot :(

Github Repository

I still haven't added a ReadMe file(working on it). But this article is sufficient to understand the working of the same.

Here is the complete Code - GitHub Repo