HiveBrain v1.2.0
Get Started
← Back to all entries
patternpythonMinor

Instagram bot script

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
scriptinstagrambot

Problem

I'm very new to Python and would like some feedback on my script. I'm fairly clueless to best practices, code correctness etc. so if there's anything at all that looks wrong, isn't 'pythonic' or could be done in a simpler way, I'd love if you could point me in the right direction.

```
#!/usr/bin/env python

"""Follows Instagram users with similar taste and likes their photos.

Scrapes users who have liked a seed user's recent photos (avoiding
users whose profiles seem spammy), then likes some of their most
popular recent photos and follows them. After 3 days, unfollows them.

Required modules:
httplib2
simplejson

Version: 2.1.8

Licensed under a BSD New license.

Uses the https://github.com/Instagram/python-instagram client.
"""

import json
import logging
import os
import random
import re
import time
from instagram import client

# CUSTOMISABLE
CONFIG = {
'client_id': '',
'client_secret': '',
'redirect_uri': '',
'access_token': '',
'client_ips': ''
}
SEED_USER = 'kevin'
NUM_TO_FOLLOW = 25
NUM_TO_UNFOLLOW = 25
# END CUSTOMISABLE

# Logging stuff
logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
logger = logging.getLogger(__name__)

# Global declarations
TILES_PATH = os.getcwd()+'/Tiles.json'

def username_to_id(username):
"""Accepts a username and returns its ID."""
user = api.user_search(q=username, count=1)
if username != user[0].username:
logger.error('Username to ID failed')
return user[0].id

def check_user(user, ids_to_avoid=[]): # TODO: Check user not super popular
"""Checks if user meets criteria to be followed, returns boolean.

Args:
user (object): An instagram.models.User object
ids_to_avoid (list): IDs to avoid, defaults to empty list
"""
if (
user.profile_picture != 'http://images.ak.instagram.com/profiles/anonymousUser.jpg'
and user.full_name
and user.bio
and re.search(r'follow|f4f|1D|one

Solution

You have an error in check_user:

def check_user(...):
    if (...):
        rel = api.user_relationship(...)
        if (...):
            return True
    else:
        return False


If the first check passes but the second doesn't, this will implicitly return None. The minimal fix is:

def check_user(...):
    if (...):
        rel = api.user_relationship(...)
        if (...):
            return True
    return False


You have a lot of code there without too much structure. First off, it's general practice to have a defined entry point function (usually main) that is called as follows, at the end of the script:

if __name__ == '__main__':
    main()


This means "if the script is being run directly (i.e. not imported), call main".

It is not clear why scrape_users is defined inline like that. I would move it up with the other function definitions, and make e.g. api a parameter. In general, you could use more explicit parameters and return values, rather than relying on scoping.

You could also split out some of the other functionality into separate functions, e.g. unfollow and follow_and_like. This would make your main very simple and avoid the current situation where you can't see the try and except KeyboardInterrupt without a lot of scrolling.

Good work on following the style guide. One minor thing (emphasis mine):


Imports should be grouped in the following order:



  • standard library imports



  • related third party imports



  • local application/library specific imports





You should put a blank line between each group of imports.

Finally, you could consider giving this a CLI to provide the various config values. Look into e.g. argparse for dealing with arguments.

Code Snippets

def check_user(...):
    if (...):
        rel = api.user_relationship(...)
        if (...):
            return True
    else:
        return False
def check_user(...):
    if (...):
        rel = api.user_relationship(...)
        if (...):
            return True
    return False
if __name__ == '__main__':
    main()

Context

StackExchange Code Review Q#58804, answer score: 4

Revisions (0)

No revisions yet.