ohld / igbot

🐙 Free scripts, bots and Python API wrapper. Get free followers with our auto like, auto follow and other scripts!
https://hikerapi.com/p/N2P6iqiM
Apache License 2.0
4.72k stars 1.47k forks source link

Duplicate likes and follows #351

Closed romankk closed 7 years ago

romankk commented 7 years ago

Purpose of your issue?

Paste the output of python3 -V here: Code: Python 3.5.3

"""
    instabot example

    Workflow:
        Like and follow users who liked the last media of input users.
"""

import sys
import os
from tqdm import tqdm
import argparse

sys.path.append(os.path.join(sys.path[0], '../'))
from instabot import Bot

parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-u', type=str, help="username")
parser.add_argument('-p', type=str, help="password")
parser.add_argument('-proxy', type=str, help="proxy")
parser.add_argument('users', type=str, nargs='+', help='users')
args = parser.parse_args()

bot = Bot()
bot.login(username="XXXXXX", password="XXXXXX",
          proxy=args.proxy)

for username in args.users:
    medias = bot.get_user_medias(username, filtration=False)
    if len(medias):
        likers = bot.get_media_likers(medias[0])
        for liker in tqdm(likers):
            bot.like_user(liker, amount=3)
            bot.follow(liker)

Describe your issue

I created two separate Instagram accounts and created for them separate scripts like_and_follow_last_user_media_likers_1.py like_and_follow_last_user_media_likers_2.py

Workflow Scripts are run manually one after another from the same folder "examples"

  1. Run script 1 with user1 "python3 like_and_follow_last_user_media_likers_1.py user1"
  2. Then I run second script for the same user1 "python3 like_and_follow_last_user_media_likers_2.py user1"

Result/Issue I'm getting duplicates likes and follows on the same followers and I can see duplicates entry in followed.txt I assumed that script is checking followed.txt before processing followers from user1 exactly for the purpose of avoiding repetitive likes and followings?

BobZombiE69 commented 7 years ago

if youhave more than 1 account , you have to run them from different folders for example: /root/instabot-account1/... /root/instabot-account2/...

ohld commented 7 years ago

Yes, that is the easiest solution.

romankk commented 7 years ago

Solution proposed above is not going to work for me. I need all accounts to run from the same folder so they share "followed.txt" and "skipped.txt" for that I tried to use "bot.follow_users" instead of "bot.follow" my code is the same as above except last line

bot.follow_users(liker)

I'm trying to filter the same user that was "liked" by "bot.like_user" but instead I'm getting other user to be followed and actually I end up with a list of users and they all get filtered. Here is log of my bot with 0 followings. questions: why "bot.follow_users" is not working?

 2017-11-07 22:26:14,153 - INFO - Instabot Started
2017-11-07 22:26:16,592 - INFO - Login success as XXXXXXXX!
  0%|                                                   | 0/388 [00:00<?, ?it/s]
 My own following list is empty , downloading ...

2017-11-07 22:26:23,479 - INFO - Liking user_4070053893's feed:
2017-11-07 22:26:24,028 - INFO - Received 18 medias.
2017-11-07 22:26:24,028 - INFO - After filtration 18 medias left.
2017-11-07 22:26:24,028 - INFO - Going to like 3 medias.
2017-11-07 22:26:44,979 - INFO - DONE: Total liked 3 medias.
2017-11-07 22:26:44,980 - INFO - Going to follow 10 users.0:20<00:00,  5.71s/it]

 Going to follow 10 user_ids ...

 After filtering followedlist.txt and skippedlist.txt, [ 7 ] user_ids left to fo                                                                                                             llow.

  0%|                                                     | 0/7 [00:00<?, ?it/s]
 ===> Going to Follow user_id: 4

 USER_NAME: mikeyk , FOLLOWER: 346401 , FOLLOWING: 772

 info :  is VERIFIED , Skipping

 Add user_id 4 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt
 14%|██████▍                                      | 1/7 [00:03<00:23,  3.84s/it]
 ===> Going to Follow user_id: 5

 USER_NAME: abbott , FOLLOWER: 17840 , FOLLOWING: 599

 user_info["follower_count"] > self.max_followers_to_follow , Skipping

 Add user_id 5 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt
 29%|████████████▊                                | 2/7 [00:07<00:18,  3.72s/it]
 ===> Going to Follow user_id: 8

 USER_NAME: brow , FOLLOWER: 3365 , FOLLOWING: 3

 user_info["follower_count"] > self.max_followers_to_follow , Skipping

 Add user_id 8 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt
 43%|███████████████████▎                         | 3/7 [00:10<00:14,  3.69s/it]
2017-11-07 22:27:00,003 - WARNING - Request return 404 error!

 USER_NAME: brow , FOLLOWER: 3365 , FOLLOWING: 3

 user_info["follower_count"] > self.max_followers_to_follow , Skipping

 Add user_id 0 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt

 57%|█████████████████████████▋                   | 4/7 [00:14<00:11,  3.81s/it]
2017-11-07 22:27:04,299 - WARNING - Request return 404 error!

 USER_NAME: brow , FOLLOWER: 3365 , FOLLOWING: 3

 user_info["follower_count"] > self.max_followers_to_follow , Skipping

 Add user_id 7 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt

 71%|████████████████████████████████▏            | 5/7 [00:19<00:07,  3.96s/it]
2017-11-07 22:27:07,350 - WARNING - Request return 404 error!

 USER_NAME: brow , FOLLOWER: 3365 , FOLLOWING: 3

 user_info["follower_count"] > self.max_followers_to_follow , Skipping

 Add user_id 9 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt

 86%|██████████████████████████████████████▌      | 6/7 [00:22<00:03,  3.68s/it]
 ===> Going to Follow user_id: 3

 USER_NAME: kevin , FOLLOWER: 1491379 , FOLLOWING: 627

 info :  is VERIFIED , Skipping

 Add user_id 3 to skippedlist : skipped.txt ...
2017-11-07 22:27:10,997 - INFO - DONE: Total followed 0 users.
  0%|                                         | 1/388 [00:51<5:34:41, 51.89s/it]
 USER_NAME: gulzhan_abay , FOLLOWER: 48 , FOLLOWING: 239

 info :  is PRIVATE , !!!
2017-11-07 22:27:14,891 - INFO - Going to follow 10 users.

 Going to follow 10 user_ids ...

 After filtering followedlist.txt and skippedlist.txt, [ 2 ] user_ids left to fo                                                                                                             llow.

  0%|                                                     | 0/2 [00:00<?, ?it/s]
2017-11-07 22:27:18,760 - WARNING - Request return 404 error!

 USER_NAME: gulzhan_abay , FOLLOWER: 48 , FOLLOWING: 239

 ["following_count"] / ["follower_count"] > self.max_following_to_followers_rati                                                                                                             o , Skipping

 Add user_id 1 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt

 50%|██████████████████████▌                      | 1/2 [00:03<00:03,  3.83s/it]
2017-11-07 22:27:22,035 - WARNING - Request return 404 error!

 USER_NAME: gulzhan_abay , FOLLOWER: 48 , FOLLOWING: 239

 ["following_count"] / ["follower_count"] > self.max_following_to_followers_rati                                                                                                             o , Skipping

 Add user_id 2 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt
2017-11-07 22:27:22,061 - INFO - DONE: Total followed 0 users.
  1%|▏                                        | 2/388 [01:02<4:15:02, 39.64s/it]
 USER_NAME: minachopard , FOLLOWER: 167 , FOLLOWING: 553

 ["following_count"] / ["follower_count"] > self.max_following_to_followers_rati                                                                                                             o , Skipping

 Add user_id 4018069515 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt
2017-11-07 22:27:25,355 - INFO - Going to follow 10 users.

 Going to follow 10 user_ids ...

 After filtering followedlist.txt and skippedlist.txt, [ 1 ] user_ids left to fo                                                                                                             llow.

  0%|                                                     | 0/1 [00:00<?, ?it/s]
 ===> Going to Follow user_id: 6

 USER_NAME: nicole , FOLLOWER: 44382 , FOLLOWING: 716

 user_info["follower_count"] > self.max_followers_to_follow , Skipping

 Add user_id 6 to skippedlist : skipped.txt ...
2017-11-07 22:27:28,143 - INFO - DONE: Total followed 0 users.
  1%|▎                                        | 3/388 [01:09<3:09:46, 29.57s/it]
 USER_NAME: sweatface891 , FOLLOWER: 689 , FOLLOWING: 1690

 ["following_count"] / ["follower_count"] > self.max_following_to_followers_rati                                                                                                             o , Skipping

 Add user_id 4270402572 to skippedlist : skipped.txt ...
Done adding user_id to skipped.txt
2017-11-07 22:27:31,575 - INFO - Going to follow 10 users.
romankk commented 7 years ago

And how I reopen ticket? @ohld

pxtyr commented 7 years ago

Why not use only one script? ie: only 'like_and_follow_last_user_media_likers_1.py'

this will share both account limits in followed.txt and skipped.txt with no duplicates.

execute for separate accounts by calling usernames and other input from command line.

python like_and_follow_last_user_media_likers_1.py -u <username> <hashtag>

romankk commented 7 years ago

@pxtyr @ohld @BobZombiE69 Just double checked proposed solution with -u key. Not working. I scrape the same user from two different accounts and end up with both accounts follow and liked the same users. From what I can see from bot.follow.py the only function that utilize followed.txt is follow_users - user_ids = list((set(user_ids) - set(followed_list)) - set(skipped_list)) the follow function is only appending users to followed.txt but then doing nothing to check if this user was already added previously. follow function is only checking against users that are already followed by my account. In my case I run daily unfollow_non_followers.py script. For that if I unsubscribe from the user because he/she did not followed me back, I probably end following this user again. Can it be fixed?

pxtyr commented 7 years ago

like_and_follow_last_user_media_likers_1.py should be using bot_follow.py and in turn appending followed.txt. Further it should be calling 'check_user' function which checks both unfollow.txt and follwed.txt --- not sure I comprehend your problem.

romankk commented 7 years ago

@pxtyr @ohld @BobZombiE69 Appreciate your reply pxtyr, From what I can understand from the code 'check_user' function does not check unfollow.txt and followed.txt check_user lead to filter_users in bot_filter.py

def filter_users(self, user_id_list):
    return [str(user["pk"]) for user in user_id_list]

filter_users downloads list of your user followed list and checks user id that your trying to follow if you already following that id or not. This function does not check if you previously liked or followed and then unfollowed that user id. That is why on Aug 3 BobZombiE69 made a commit https://github.com/instagrambot/instabot/commit/167c62e2650bb4eaee6c1df1fdc591a84a35ad94 but he fixed only "follow_users" function. Correct me if I'm wrong.

pxtyr commented 7 years ago

Checked code ---- it looks like follow.py lacks "refollow" precaution. I am looking at same problem and thought it was doing follow.py doing it. But it makes sense, as I was probably looking at follow_users.py... confusing..

I'm working on finding solution in follow.py to solve your same problem of avoiding "refollow" as well as to make it more efficient. I think this makes excessive requests, especially in check_user ( ie. it calls get_user_following upon every individual user).

unless @ohld or someone else already has solution, i will come back with modified code for you to look at.

cheers

romankk commented 7 years ago

@pxtyr Here what I got. you need to have user_likers.txt in the same dir with follow_users_from_file_2.py

"""
    instabot example

    Workflow:
        Save all likers from last 3 pics from the selected users 
"""

import sys
import os
import argparse

sys.path.append(os.path.join(sys.path[0], '../'))
from instabot import Bot

parser = argparse.ArgumentParser(add_help=True)
parser.add_argument('-u', type=str, help="username")
parser.add_argument('-p', type=str, help="password")
parser.add_argument('-proxy', type=str, help="proxy")
parser.add_argument('users', type=str, nargs='+', help='users')
args = parser.parse_args()

bot = Bot(filter_users=True)
bot.login(username=args.u, password=args.p,
          proxy=args.proxy)
f = open('user_likers.txt', 'r+')
for username in args.users:
    medias = bot.get_user_medias(username, filtration=False)
    if len(medias):
        likers = bot.get_media_likers(medias[0])
        for likers in likers:
            f.write("%d\r" % (int(likers)))
        likers = bot.get_media_likers(medias[1])
        for likers in likers:
            f.write("%d\r" % (int(likers)))
        likers = bot.get_media_likers(medias[2])
        for likers in likers:
            f.write("%d\r" % (int(likers)))

f = open('user_likers.txt', 'r+') #reread updated file
users_ids = list(f)
print("Found %d users in file." % len(users_ids))
bot.follow_users(users_ids)

then I modified 2 functions in bot_follow.py "follow" and "follow_users"

from tqdm import tqdm

from . import limits
from . import delay
from .bot_like import like_user
from .bot_filter import check_user

def follow(self, user_id, filtration=True):
    user_id = self.convert_to_user_id(user_id)
    if filtration:
        if not self.check_user(user_id, filter_closed_acc=True):
            return False
    print('\n ===> Going to Follow user_id: %s ' % (user_id))  # Log to console
#    if not self.check_user(user_id):
    #user_id = self.convert_to_user_id(user_id)
#        return True
    if limits.check_if_bot_can_follow(self):
        delay.follow_delay(self)
        if super(self.__class__, self).follow(user_id):
            print('\n\033[92m ===> FOLLOWED <==== user_id: %s \033[0m' % (
                user_id))  # Log to console
            self.total_followed += 1
            # Log to console
            print(
                '\n\033[92m Writing user_id to file : followed.txt ... \033[0m')
            with open('followed.txt', 'a') as file:  # Appending user_id to the followed.txt
                # Appending user_id to the followed.txt
                file.write(str(user_id) + "\n")
            return True
    else:
        self.logger.info("Out of follows for today.")
    return False

def follow_users(self, user_ids):
    broken_items = []
    if not limits.check_if_bot_can_follow(self):
        self.logger.info("Out of follows for today.")
        return
    self.logger.info("Going to follow %d users." % len(user_ids))
    followed_list = self.read_list_from_file(
        "followed.txt")   # Read followed.txt file
    skipped_list = self.read_list_from_file(
        "skipped.txt")  # Read skipped.txt file
    print('\n\033[92m Going to follow %s user_ids ...\033[0m' %
          len(user_ids))  # Log to console
    # remove skipped and followed list from
    user_ids = list((set(user_ids) - set(followed_list)) - set(skipped_list))
    # user_ids = list(set(user_ids))
    print('\n\033[92m After filtering followedlist.txt and skippedlist.txt, [ %s ] user_ids left to follow. \033[0m' % len(
        user_ids))  # Log to console
    for user_id in tqdm(user_ids):
        self.like_user(user_id.rstrip(), amount=3)  # rstrip() - strip the \n
        self.follow(user_id.rstrip())
        """if not self.follow(user_id.rstrip()):
            delay.error_delay(self)
            broken_items = user_ids[user_ids.index(user_id):]
            break"""
    self.logger.info("DONE: Total followed %d users." % self.total_followed)
    return broken_items

def follow_followers(self, user_id, nfollows=None):
    self.logger.info("Follow followers of: %s" % user_id)
    if not limits.check_if_bot_can_follow(self):
        self.logger.info("Out of follows for today.")
        return
    if not user_id:
        self.logger.info("User not found.")
        return
    follower_ids = self.get_user_followers(user_id, nfollows)
    if not follower_ids:
        self.logger.info("%s not found / closed / has no followers." % user_id)
    else:
        self.follow_users(follower_ids[:nfollows])

def follow_following(self, user_id, nfollows=None):
    self.logger.info("Follow following of: %s" % user_id)
    if not limits.check_if_bot_can_follow(self):
        self.logger.info("Out of follows for today.")
        return
    if not user_id:
        self.logger.info("User not found.")
        return
    following_ids = self.get_user_following(user_id)
    if not following_ids:
        self.logger.info("%s not found / closed / has no following." % user_id)
    else:
        self.follow_users(following_ids[:nfollows])

Here is issues with this code:

  1. user_ids = list((set(user_ids) - set(followed_list)) - set(skipped_list)) seems not completely working, I still end up with refolowing users_id's that are already in followed list... I'm not sure why.
  2. check_user is run on "follow" and on "like" functions. Ideally if user_id not pass check_user for like function it should get "thrown away".
  3. errors handling is not working - """if not self.follow(user_id.rstrip()): delay.error_delay(self) broken_items = user_ids[user_ids.index(user_id):] break""" I don't know why

All suggestions are welcome and appreciated

romankk commented 7 years ago

Regarding 1st issue from above: "user_ids = list((set(user_ids) - set(followed_list)) - set(skipped_list)) seems not working, I still end up with refolowing users_id's that are already in followed list... I'm not sure why." I removed "read_list_from_file" from bot_follow.py and now "user_ids = list((set(user_ids) - set(followed_list)) - set(skipped_list))" is working as intended.

from tqdm import tqdm

from . import limits
from . import delay
from .bot_like import like_user
from .bot_filter import check_user

def follow(self, user_id, filtration=True):
    user_id = self.convert_to_user_id(user_id)
    if filtration:
        if not self.check_user(user_id, filter_closed_acc=True):
            return False
    print('\n ===> Going to Follow user_id: %s ' % (user_id))  # Log to console
#    if not self.check_user(user_id):
    #user_id = self.convert_to_user_id(user_id)
#        return True
    if limits.check_if_bot_can_follow(self):
        delay.follow_delay(self)
        if super(self.__class__, self).follow(user_id):
            print('\n\033[92m ===> FOLLOWED <==== user_id: %s \033[0m' % (
                user_id))  # Log to console
            self.total_followed += 1
            # Log to console
            print(
                '\n\033[92m Writing user_id to file : followed.txt ... \033[0m')
            with open('followed.txt', 'a') as file:  # Appending user_id to the followed.txt
                # Appending user_id to the followed.txt
                file.write(str(user_id) + "\n")
            return True
    else:
        self.logger.info("Out of follows for today.")
    return False

def follow_users(self, user_ids):
    broken_items = []
    if not limits.check_if_bot_can_follow(self):
        self.logger.info("Out of follows for today.")
        return
    self.logger.info("Going to follow %d users." % len(user_ids))
    followed_list = open("followed.txt", 'r+')
    skipped_list = open("skipped.txt", 'r+')
    """followed_list = self.read_list_from_file(
        "followed.txt")   # Read followed.txt file
    skipped_list = self.read_list_from_file(
        "skipped.txt")  # Read skipped.txt file"""
    print('\n\033[92m Going to follow %s user_ids ...\033[0m' %
          len(user_ids))  # Log to console
    # remove skipped and followed list from
    user_ids = list((set(user_ids) - set(followed_list)) - set(skipped_list))
    print('\n\033[92m After filtering followedlist.txt and skippedlist.txt, [ %s ] user_ids left to follow. \033[0m' % len(
        user_ids))  # Log to console
    for user_id in tqdm(user_ids):
        self.like_user(user_id.rstrip(), amount=3)  # rstrip() - strip the \n
        self.follow(user_id.rstrip())
        """if not self.follow(user_id.rstrip()):
            delay.error_delay(self)
            broken_items = user_ids[user_ids.index(user_id):]
            break"""
    self.logger.info("DONE: Total followed %d users." % self.total_followed)
    return broken_items

def follow_followers(self, user_id, nfollows=None):
    self.logger.info("Follow followers of: %s" % user_id)
    if not limits.check_if_bot_can_follow(self):
        self.logger.info("Out of follows for today.")
        return
    if not user_id:
        self.logger.info("User not found.")
        return
    follower_ids = self.get_user_followers(user_id, nfollows)
    if not follower_ids:
        self.logger.info("%s not found / closed / has no followers." % user_id)
    else:
        self.follow_users(follower_ids[:nfollows])

def follow_following(self, user_id, nfollows=None):
    self.logger.info("Follow following of: %s" % user_id)
    if not limits.check_if_bot_can_follow(self):
        self.logger.info("Out of follows for today.")
        return
    if not user_id:
        self.logger.info("User not found.")
        return
    following_ids = self.get_user_following(user_id)
    if not following_ids:
        self.logger.info("%s not found / closed / has no following." % user_id)
    else:
        self.follow_users(following_ids[:nfollows])
pxtyr commented 7 years ago

cool.. i will take a look-- may I ask, (because I still don't fully understand) --- what is the objective of the code; what is it you are working to obtain here?

romankk commented 7 years ago
  1. I want to avoid refollowing ( I have 3 accounts that are targeting the same audience)
  2. I'm going after "active" users who are liking particular user media.
  3. Bot needs to be humanlike, it needs to like and then follow targeted user.