Instapy: Ability to interact with users who liked the specific post

Created on 7 May 2018  路  4Comments  路  Source: timgrossmann/InstaPy

Question

Hello guys! Is there an ability to interact with users who liked a specific post? If no, could someone help to implement it? Yesterday I tried to add a new method based on the "interact_user_followers" to instapy.py and unfollow.py, but instead of username I used post ID (like "Bid2_-RDX9r"), and instead of Followers link I found the "Likes" link. So, it worked for me, the specific post opened, the "Likes" window opened and scroll worked correctly, list of users was successfully fetched. But, I faced the problem, when the amount of users is large (more than 150 e.g.), this script fails on the following lines:

_person_list.append(person.find_element_by_xpath(
"../../../*").find_elements_by_tag_name("a")[1].text)_

Looks like the script can't find the elements by xpath, because the error message is "out of range"). But when the number of users e.g. 50 it works correctly. Could someone help? Thank you in advance!

session.interact_post_likers(['Bid2_-RDX9r'], amount=300, randomize=True)

Here's the "interact_post_likers" method (copy of "interact_user_followers", a bit changed)

instapy.py configuration

def interact_post_likers(self, usernames, amount=10, randomize=False):

    userToInteract = []
    if not isinstance(usernames, list):
        usernames = [usernames]
    try:
        for user in usernames:

            user = get_given_post_likers(self.browser,
                                            user,
                                            amount,
                                            self.dont_include,
                                            self.username,
                                            randomize,
                                            self.logger)
            if isinstance(user, list):
                userToInteract += user
    except (TypeError, RuntimeWarning) as err:
        if isinstance(err, RuntimeWarning):
            self.logger.warning(
                u'Warning: {} , stopping follow_users'.format(err))
            return self
        else:
            self.logger.error('Sorry, an error occured: {}'.format(err))
            self.aborting = True
            return self

    self.logger.info('--> Users: {} \n'.format(len(userToInteract)))
    userToInteract = random.sample(
        userToInteract,
        int(ceil(
            self.user_interact_percentage * len(userToInteract) / 100)))

    self.like_by_users(userToInteract,
                       self.user_interact_amount,
                       self.user_interact_random,
                       self.user_interact_media)

    return self

Here's the "get_given_post_likers" method

unfollow_util.py configuration

def get_given_post_likers(browser, post_link, amount, dont_include, login, randomize, logger):
"""
Get the followers of the user

:param browser: webdriver instance
:param user_name: the user who's followers to retrieve
:param amount: limit the number of users to this
:param dont_include: not used
:param login: not used
:param randomize: randomize the list of users
:param logger: logger instance
:return:
    list of followers links
    None on error
"""

post_link = post_link.strip()

browser.get('https://www.instagram.com/p/' + post_link)
# update server calls
update_activity()

try:
    allfollowing = format_number(
        browser.find_element_by_xpath('//*[@id="react-root"]/section/main/div/div/article/div[2]/section[2]/div/a/span').text)
except NoSuchElementException:
    logger.warning('Can\'t find the likers count')
    return
try:
    likes_link = browser.find_element_by_xpath(
        '//*[@id="react-root"]/section/main/div/div/article/div[2]/section[2]/div/a')
except NoSuchElementException:
    logger.error('Could not find likes link for {}'.format(post_link))
    return
click_element(browser, likes_link)
# update server calls
update_activity()

sleep(2)

# find dialog box
dialog = browser.find_element_by_xpath(
    "//div[text()='Likes']/following-sibling::div")

# scroll down the page
scroll_bottom(browser, dialog, allfollowing)
follow_buttons = dialog.find_elements_by_xpath(
    "//div/div/span/button[text()='Follow']")

abort = False
try_again = 0   ##ADD this line
sc_rolled = 0   #ADD this line
total_list = len(follow_buttons)

while (total_list < amount) and not abort:
    before_scroll = total_list
    for i in range(3):
        scroll_bottom(browser, dialog, 2)
        sc_rolled += 1
        sleep(random.randint(1, 2))
    follow_buttons = dialog.find_elements_by_xpath(
        "//div/div/span/button[text()='Follow']")
    total_list = len(follow_buttons)
    abort = (before_scroll == total_list)
    if abort:
        if total_list < amount:
            logger.info("Failed to load desired amount of users.")
    if sc_rolled > 85:   #you may want to use up to 100
        if total_list < amount:
            logger.info("Too many requests sent..  ~ sleeping a bit  |  attempt: {}  |  gathered links: {}".format(try_again+1, total_list))
            sleep(random.randint(600, 655))
            try_again += 1
            sc_rolled = 0

# get follow buttons. This approch will find the follow buttons and
# ignore the Unfollow/Requested buttons.

person_list = []

if amount >= len(follow_buttons):
    amount = len(follow_buttons)
    logger.warning("{} -> Less users to follow than requested. == {} "
                   .format(post_link, str(amount)))

finalBtnPerson = []
if randomize:
    sample = random.sample(range(0, len(follow_buttons)), amount)

    for num in sample:
        finalBtnPerson.append(follow_buttons[num])
else:
    finalBtnPerson = follow_buttons[0:amount]
for person in finalBtnPerson:

    if person and hasattr(person, 'text') and person.text:
        person_list.append(person.find_element_by_xpath(
            "../../../*").find_elements_by_tag_name("a")[1].text)

return person_list
feature request

Most helpful comment

@uluQulu Omg, why I didn't see these function yesterday? Thanks, now it works fine! :)
Actually, I'm not a python developer. I'm not a developer at all :D but using the existing code decided to make a function for my own purposes :)

All 4 comments

hi @sanyco92,
You can use users_liked function which returns the list of users who like the post

.commenters_util import users_liked

And I wonder how do you get pics' URLs effectively :P
BTW instead of newly written code, you can use interact_by_users already existing feature inside your interact_post_likers new feature...

@uluQulu Omg, why I didn't see these function yesterday? Thanks, now it works fine! :)
Actually, I'm not a python developer. I'm not a developer at all :D but using the existing code decided to make a function for my own purposes :)

Is this a feature request that can be implemented? @sanyco92 how are you getting the post URLs?

I don't think the "users_liked" function is working as expected. It returns dates and my own name in the likers names list.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Spyd3r0us picture Spyd3r0us  路  3Comments

rahulkapoor90 picture rahulkapoor90  路  3Comments

n0sw34r picture n0sw34r  路  3Comments

harrypython picture harrypython  路  3Comments

seuraltimez picture seuraltimez  路  3Comments