Python Selenium Webdriver Cannot Locate an Element on a Pop Up Page in Instagram

Viewed 82

First of all sorry for my junky coding, I am not a coder of any sort.

I created (copied xd) an Instagram bot like a year ago, and it was working absolutely fine until two months ago. My goal with my Instagram bot is to identify new followers and unfollowers and stuff for my main account. I don't do rapid followings and unfollowings. The problem is when I open the following popup on Instagram, selenium cannot find any element that I specify. I've tried using XPATH, CSS Selector, by class name and all those methods. But I cannot even click the close button after I open that popup page, the code cannot find the button. Do you guys have any ideas why or any suggestions?

last_ht, ht = 0, 1
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.XPATH, "//div[@class=_aano]")))
scroll_box = self.browser.find_element_by_xpath("//div[@class=_aano]")
while last_ht != ht:
    last_ht = ht
    time.sleep(2.5)
    ht = self.browser.execute_script(
        "arguments[0].scrollTo(0, arguments[0].scrollHeight);"
        "return arguments[0].scrollHeight;", scroll_box)

The code above should wait for the Following button on your profile page and then click it (there is nothing wrong until there), and then wait for the popup to load and then scroll, but the WebDriverWait function raises an error, meaning the code cannot find the element, but like I can literally see it. It waits for 10 seconds.

I've tried Chrome and then Firefox, but it was even worse in Mozilla, it couldn't locate the Followings button on the profile page.

2 Answers

Since you haven't shared the applicable part of the DOM, my best guess is that the element you need to interact with is located inside an iframe. To interact with components inside an iframe, you must switch to the iframe first (which means you need to write a locator for the iframe, and then execute the rest of your code.

last_ht, ht = 0, 1
# you must provide the xpath string for the iframe
driver.switch_to.frame(driver.find_element_by_xpath("..."))
WebDriverWait(self.browser, 10).until(EC.presence_of_element_located((By.XPATH, "//div[@class=_aano]"))) 
scroll_box = self.browser.find_element_by_xpath("//div[@class=_aano]")
while last_ht != ht:
    last_ht = ht
    time.sleep(2.5)
    ht = self.browser.execute_script(
        "arguments[0].scrollTo(0, arguments[0].scrollHeight);"
        "return arguments[0].scrollHeight;", scroll_box)
# the rest of your code

Once you finish with the components in the iframe, you must switch back to the parent frame.

driver.switch_to.parent_frame()

Or switch to the top window

driver.switch_to.default_content()

Try them in that order. I am sure the first one will work for you.

My goal with my Instagram bot is to identify new followers and unfollowers and stuff for my main account

So you should click "followers" button instead of "following" button, like you said here.

The code above should wait for the Following button on your profile page

So, assume that's what you need, this code will help you scroll down the "followers" popup. I put the whole code here because i don't know if your code clicked the "followers" button or not. Also, the:

last_ht, ht = 0, 1
while last_ht != ht:
    last_ht = ht

part will make your scrolling down action run only once, quite weird that they use 3 lines of code for doing nothing. just remove that part and your code will do exact same thing it previously does. So I use a for loop here instead.

Things to change to use the code:

  • Put your username and password in these two lines:

INS_EMAIL = "youremail@gmail.com" INS_PASSWORD = "yourpassword"

  • Fix the link in this line to your ins account link:

self.driver.get("https://www.instagram.com/geeks_for_geeks/")

  • Change "followers" to "following" depend on your use case:
followers = WebDriverWait(self.driver, 10).until(
    EC.presence_of_element_located((
        By.PARTIAL_LINK_TEXT,
        'followers')))
  • I'm using a 100 times for loop but if you want to scroll until it reaches the end of the file, guess I can change that later.

  • Next time you should post longer code so we can understand if other parts are working or not.

from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import os

# ------------ CONSTANTS ------------- #

INS_EMAIL = 'youremail@gmail.com'
INS_PASSWORD = 'yourpassword'
INS_URL = 'https://instagram.com'


class InstaFollower:

    def __init__(self):
        s = Service(ChromeDriverManager().install())
        self.driver = webdriver.Chrome(service=s)

    def login(self):
        self.driver.get(INS_URL)

        time.sleep(3)

        username_input_tag = WebDriverWait(self.driver,
                10).until(EC.presence_of_element_located((By.XPATH,
                          "//input[@name='username']")))
        username_input_tag.send_keys(INS_EMAIL)

        password_input_tag = WebDriverWait(self.driver,
                10).until(EC.presence_of_element_located((By.XPATH,
                          "//input[@name='password']")))
        password_input_tag.send_keys(INS_PASSWORD)
        password_input_tag.send_keys(Keys.ENTER)

    def find_followers(self):
        time.sleep(2)

        self.driver.get('https://www.instagram.com/geeks_for_geeks/')

        # change the link above to your instagram link

        time.sleep(3)

        followers = WebDriverWait(self.driver,
                                  10).until(EC.presence_of_element_located((By.PARTIAL_LINK_TEXT,
                'followers')))

        # The line above is optional, you can change followers to following

        followers.click()

        time.sleep(3)

        try:
            popup = self.driver.find_element(By.CSS_SELECTOR, '._aano')
        except:
            print 'FAILED TO FIND POPUP ELEMENT'
        else:

            print 'Popup element is found'

        for run in range(100):
            print(f"scrolling down {run}")
            self.driver.execute_script('arguments[0].scrollTop = arguments[0].scrollHeight'
                    , popup)
            time.sleep(2)


insta_follower_bot = InstaFollower()
insta_follower_bot.login()
time.sleep(2)
insta_follower_bot.find_followers()

I'm curious to know your result because I'm currently working on the similar project.

Added a lot of time.sleep because the libary's internet is so badddd

Related