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)
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
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
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.
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 :)