Search code examples
pythonseleniumgoogle-ads-api

Element showing on screen but only added to DOM after Inspection or clicking


I'm trying to use selenium to download reports from Google Ads, the script is working fine until I try to click the Campaign-wide target button in the image, It's not showing in the DOM and selenium can't see it until I click/inspect it that it's accessible. enter image description here

I tried to switch frames and search for it but to no avail, I have only two frames when I try

iframes = b.driver.find_elements(By.XPATH, "//iframe")

Code:

from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from time import sleep

from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
import csv


class Bot:
    def __init__(self, user_data_dir=None, profile_dir=None, csv_filename=None):
        self.__service = ChromeService(ChromeDriverManager().install())
        self.user_data_dir = user_data_dir 
        self.profile_dir = profile_dir
        self.__options = webdriver.ChromeOptions()
        self.__options.add_argument(f"user-data-dir={self.user_data_dir}")
        self.__options.add_argument(f"--profile-directory={self.profile_dir}")
        self.csv_filename = csv_filename or "data.csv"

        self.driver = webdriver.Chrome(service=self.__service, options=self.__options)
 
    def login(self):
        self.driver.get("https://ads.google.com")
        sleep(1)

        try:
            # get the sign in button and click it
            sign_in_btn = self.driver.find_element(By.XPATH, '//*[@id="header-topbar"]/div/div[3]/div/div[3]/a')
            sign_in_btn.click()
            sleep(2)

            
        except Exception as e:
            print(e)
            # if the sign in button is not found, try clicking the drawer menu button and then the sign in button
            drawer_btn = self.driver.find_element(By.XPATH, '//*[@id="header-drawer"]/div/div/div/div[1]/div/button')
            drawer_btn.click()
            sleep(2)
            
            sign_in_btn = self.driver.find_element(By.XPATH, '//*[@id="header-topbar"]/div/div[3]/div/div[3]/a')
            sign_in_btn.click()
            sleep(2)

        finally:
            accnt_btn = self.driver.find_element(By.XPATH, '/html/body/div[1]/root/div[2]/nav-view-loader/multiaccount-view/div/div[2]/div/div[1]/material-list/material-list-item[4]/div/div[1]')
            accnt_btn.click()
            sleep(5)

    
    def do(self):

        self.login()
        # get the campaigns button dropdown button and click it
        campaigns_drpdwn_btn = self.driver.find_element(By.XPATH, '/html/body/div[2]/root/div/div[1]/div/div/div[3]/div/div/awsm-skinny-nav/nav/div[1]/div[3]/awsm-skinny-nav-item[1]/a/material-ripple')
        campaigns_drpdwn_btn.click()
        sleep(2)

        # TODO get all the campaigs lists and click on each one of them
        # get a certain campaign and click it
        campaign_btn = self.driver.find_element(By.XPATH, '//*[@id="cmExtensionPoint-id"]/base-root/div/div[2]/div[1]/view-loader/campaign-view/tableview/div[6]/ess-table/ess-particle-table/div[1]/div/div[2]/div[3]/ess-cell[2]/campaign-name/campaign-name-generic/a')
        campaign_btn.click()
        sleep(2)

        # campaign more details button
        campaign_more_details_btn = self.driver.find_element(By.XPATH, '/html/body/div[2]/root/div/div[1]/div/div/div[3]/div/content-header/deferred-infosnack/infosnack/div/div[1]/review-panel-trigger/button/div[2]')
        campaign_more_details_btn.click()
        sleep(5)


        # get the bid strategy button, using the 'Maximize conversions' text as a span and click it
        campaign_bid_strategy_btn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Maximize conversions')]")
        campaign_bid_strategy_btn.click()
        sleep(4)

        # get the campaign simulator button and click it
        campaign_sim_btn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Campaign simulator')]")
        campaign_sim_btn.click()
        sleep(2)

        # get the campaign simulator target dropdown and click it [%, campaign wide target]
        campaign_sim_target_dropdn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Target scaling')]")
        campaign_sim_target_dropdn.click()
        sleep(2)

        campaign_wide_target_btn = self.driver.find_element(By.XPATH, "//span[contains(text(), 'Campaign-wide target')]")
        campaign_wide_target_btn.click()
        sleep(2)

I'm trying to get selenium to see the button, any help would be appreciated.


Solution

  • The Solution was to simulate my interaction using ActionChains https://www.selenium.dev/documentation/webdriver/actions_api/,

    Code:

    select_click = ActionChains(self.driver)
    select_click.move_to_element(campaign_sim_target_dropdn)
    select_click.send_keys(Keys.ARROW_DOWN)
    select_click.send_keys(Keys.ENTER)
    select_click.perform()
    

    Then the element was added to the DOM and I was able to access it with XPATH