BaSs_HaXoR

Instagrambot (python)

Feb 27th, 2015 (edited)
731
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.11 KB | None | 0 0
  1. #!/usr/bin/env python
  2. # https://codereview.stackexchange.com/questions/58804/instagram-bot-script
  3. # Instagram bot script
  4. """Follows Instagram users with similar taste and likes their photos.
  5.  
  6. Scrapes users who have liked a seed user's recent photos (avoiding
  7. users whose profiles seem spammy), then likes some of their most
  8. popular recent photos and follows them. After 3 days, unfollows them.
  9.  
  10. Required modules:
  11.    httplib2
  12.    simplejson
  13.  
  14. Version: 2.1.8
  15.  
  16. Licensed under a BSD New license.
  17.  
  18. Uses the https://github.com/Instagram/python-instagram client.
  19. by Spike Padley, 2014.
  20. """
  21.  
  22. import json
  23. import logging
  24. import os
  25. import random
  26. import re
  27. import time
  28. from instagram import client
  29.  
  30. # CUSTOMISABLE
  31. CONFIG = {
  32.     'client_id': '',
  33.     'client_secret': '',
  34.     'redirect_uri': '',
  35.     'access_token': '',
  36.     'client_ips': ''
  37. }
  38. SEED_USER = 'kevin'
  39. NUM_TO_FOLLOW = 25
  40. NUM_TO_UNFOLLOW = 25
  41. # END CUSTOMISABLE
  42.  
  43. # Logging stuff
  44. logging.basicConfig(level=logging.DEBUG, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')
  45. logger = logging.getLogger(__name__)
  46.  
  47. # Global declarations
  48. TILES_PATH = os.getcwd()+'/Tiles.json'
  49.  
  50.  
  51. def username_to_id(username):
  52.     """Accepts a username and returns its ID."""
  53.     user = api.user_search(q=username, count=1)
  54.     if username != user[0].username:
  55.         logger.error('Username to ID failed')
  56.     return user[0].id
  57.  
  58.  
  59. def check_user(user, ids_to_avoid=[]):  # TODO: Check user not super popular
  60.     """Checks if user meets criteria to be followed, returns boolean.
  61.  
  62.    Args:
  63.    user (object): An instagram.models.User object
  64.    ids_to_avoid (list): IDs to avoid, defaults to empty list
  65.    """
  66.     if (
  67.         user.profile_picture != 'http://images.ak.instagram.com/profiles/anonymousUser.jpg'
  68.         and user.full_name
  69.         and user.bio
  70.         and re.search(r'follow|f4f|1D|one ?direction|bieber|shout', user.bio, re.I) is None
  71.         and user.id not in ids_to_avoid
  72.     ):
  73.         rel = api.user_relationship(user_id=user.id)
  74.         if (
  75.             rel.outgoing_status == 'none'
  76.             and rel.incoming_status != 'followed_by'
  77.             and rel.target_user_is_private is False
  78.         ):
  79.             return True
  80.     else:
  81.         return False
  82.  
  83. try:
  84.     while True:
  85.  
  86.         api = client.InstagramAPI(**CONFIG)
  87.  
  88.         # Load Tiles.json
  89.         tiles = {}
  90.         with open(TILES_PATH) as f:
  91.             tiles = json.load(f)
  92.  
  93.         # Make a list of users who are currently being followed, or have been followed before
  94.         already_followed = []
  95.         for tile in tiles['present']:
  96.             already_followed.append(tile['user_id'])
  97.         for tile in tiles['past']:
  98.             already_followed.append(tile['user_id'])
  99.  
  100.         # Scrape users
  101.         scraped_users = []
  102.  
  103.         def scrape_users():
  104.             next_url = ''
  105.             while len(scraped_users) < NUM_TO_FOLLOW:
  106.  
  107.                 recent_media, next_url = api.user_recent_media(user_id=username_to_id(SEED_USER), count=2, with_next_url=next_url)
  108.                 for media in recent_media:
  109.  
  110.                     likes = api.media_likes(media_id=media.id)
  111.                     for user in likes:
  112.  
  113.                         if check_user(user=user, ids_to_avoid=(already_followed + scraped_users)):
  114.  
  115.                             scraped_users.append(user.id)
  116.                             logger.info('Scraped user ' + user.id)
  117.  
  118.                             if len(scraped_users) >= NUM_TO_FOLLOW:
  119.                                 return
  120.                         else:
  121.                             logger.info('Avoided user ' + user.id)
  122.         scrape_users()
  123.  
  124.         logger.info('Following and liking the photos of %s users', len(scraped_users))
  125.  
  126.         # Loop through scraped_users and like their photos and follow them
  127.         for user_id in scraped_users:
  128.             try:
  129.                 recent_media, next_url = api.user_recent_media(user_id=user_id, count=12)
  130.  
  131.                 media_dict = {}
  132.                 for media in recent_media:
  133.                     media_dict[media.like_count] = media.id
  134.  
  135.                 i = 1
  136.                 for likes in sorted(media_dict.keys(), reverse=True):
  137.  
  138.                     if not 0 < likes < 300:
  139.                         continue
  140.  
  141.                     if (random.random() + (i / (1 / 0.07))) < 0.5 or i <= 2:
  142.  
  143.                         api.like_media(media_id=media_dict[likes])  # like_media doesn't return anything?
  144.                         logger.info('Liked media ' + media_dict[likes])
  145.                         time.sleep(random.randint(20, 50))
  146.  
  147.                     i += 1
  148.  
  149.                 follow = api.follow_user(user_id=user_id)
  150.                 if follow[0].outgoing_status != 'none':
  151.  
  152.                     tiles['present'].append({'user_id': user_id, 'time_followed': time.time()})
  153.                     logger.info('Followed user ' + user_id)
  154.  
  155.             except Exception, e:
  156.                 logger.error(e)
  157.  
  158.         # Work out who (if anyone) is due for unfollowing
  159.         to_unfollow = []
  160.         for tile in tiles['present']:
  161.             if (time.time() - tile['time_followed']) > (60 * 60 * 24 * 3):
  162.                     to_unfollow.append(tile)
  163.                     if len(to_unfollow) >= NUM_TO_UNFOLLOW:
  164.                         break
  165.  
  166.         logger.info('Unfollowing %s users', len(to_unfollow))
  167.  
  168.         # Unfollow users due for unfollowing
  169.         for tile in to_unfollow:
  170.             try:
  171.                 unfollow = api.unfollow_user(user_id=tile['user_id'])
  172.                 if unfollow[0].outgoing_status == 'none':
  173.  
  174.                     tiles['present'].remove(tile)
  175.                     tiles['past'].append(tile)
  176.                     logger.info('Unfollowed user ' + tile['user_id'])
  177.  
  178.             except Exception, e:
  179.                 logger.error(e)
  180.  
  181.         with open(TILES_PATH, 'w') as f:
  182.             json.dump(tiles, f)
  183.  
  184.         logger.info('Waiting 1 hour until repeat')
  185.         time.sleep(60 * 60)
  186.  
  187. except KeyboardInterrupt:
  188.     # ^C exits the script: Save Tiles.json first
  189.     with open(TILES_PATH, 'w') as f:
  190.         json.dump(tiles, f)
  191.     logger.info('Saved and exited')
Add Comment
Please, Sign In to add comment