This question already has answers here:
Unable to locate the child iframe element which is within the parent iframe through Selenium in Java
(2 answers)
Multiple iframe tags Selenium webdriver
(2 answers)
Closed 3 years ago.
I am trying to switch into second iframe of the website for personal auto-filler for my business.
Just in case I might get marked as dup, I tried Python Selenium switch into an iframe within an iframe already and sadly got not much out of it.
Here are html codes for two iframes. Second iframe is within the first one:
<div id="tab2_1" class="cms_tab_content1" style="display: block;">
<iframe id="the_iframe"src=
"http://www.scourt.go.kr/portal/information/events/search/search.jsp">
</iframe> <!-- allowfullscreen --></div>
<div id="contants">
<iframe frameborder="0" width="100%" height="1100" marginheight="0"
marginwidth="0" scrolling="auto" title="나의 사건검색"
src="http://safind.scourt.go.kr/sf/mysafind.jsp
sch_sa_gbn=&sch_bub_nm=&sa_year=&sa_gubun=&sa_serial=&x=&
y=&saveCookie="></iframe>
<noframes title="나의사건검색(새창)">
<a href="http://safind.scourt.go.kr/sf/mysafind.jspsch_sa_gbn
=&sch_bub_nm=&sa_year=&sa_gubun=&sa_serial=&x=&y=&
saveCookie=" target="_blank"
title="나의사건검색(새창)">프레임이 보이지 않을경우 이곳을 클릭해주세요</a></noframes></div>
Just for a reference- so far, I tried these:
#METHOD-1
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.ID,"the_iframe"))
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.CSS_SELECTOR,"#contants > iframe"))
#METHOD-2
driver.switch_to.frame(driver.find_element_by_xpath('//*[#id="the_iframe"]'))
driver.WAIT
driver.switch_to.frame(driver.find_element_by_css_selector('//*[#id="contants"]/iframe'))
driver.WAIT
#METHOD-3
iframe = driver.find_elements_by_tag_name('iframe')[0]
driver.switch_to.default_content()
driver.switch_to.frame(iframe)
driver.find_elements_by_tag_name('iframe')[0]
Here is the entire code I have right now:
import time
import requests
from bs4 import BeautifulSoup as SOUP
import lxml
import re
import pandas as pd
import numpy as np
from selenium import webdriver
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.remote.webelement import WebElement
from selenium.webdriver.support.ui import Select
import psycopg2
#ID and Password for autologin
usernameStr= 'personalinfo'
passwordStr= 'personalinfo'
driver = webdriver.Chrome('./chromedriver')
ultrawait = WebDriverWait(driver, 9999)
ConsumerName=""
COURTNO=""
CASENO=""
CaseYear=""
CaseBun=""
CaseSerial=""
#AutoLogin
driver.get("http://PERSONALINFO")
username = driver.find_element_by_name('userID')
username.send_keys(usernameStr)
userpassword = driver.find_element_by_name('userPassword')
userpassword.send_keys(passwordStr)
login_button=driver.find_elements_by_xpath("/html/body/div/div[2]/div/form/input")[0]
login_button.click()
#Triggered when str of URL includes words in look_for
def condition(driver):
look_for = ("SangDamPom", "jinHaengNo")
url = driver.current_url
WAIT = WebDriverWait(driver, 2)
for s in look_for:
if url.find(s) != -1:
url = driver.current_url
html = requests.get(url)
soup = SOUP(html.text, 'html.parser')
soup = str(soup)
#Some info crawled
CN_first_index = soup.find('type="text" value="')
CN_last_index = soup.find('"/></td>\n<t')
ConsumerName=soup[CN_first_index+19:CN_last_index]
ConsumerName.replace(" ","")
#Some info crawled
CTN_first_index = soup.find('background-color:#f8f8f8;')
CTN_last_index = soup.find('</td>\n<td height="24"')
COURTNO = soup[CTN_first_index+30:CTN_last_index]
COURTNO = COURTNO.replace('\t', '')
#Some info crawled
CAN_first_index = soup.find('가능하게 할것(현제는 적용않됨)">')
CAN_last_index = soup.find('</a></td>\n<td height="24"')
CASENO=soup[CAN_first_index+19:CAN_last_index]
CaseYear=CASENO[:4]
CaseBun=CASENO[4:-5]
CaseSerial=CASENO[-5:]
print(ConsumerName, COURTNO, CaseYear, CaseBun, CaseSerial)
#I need to press this button for iframe I need to appear.
frame_button=driver.find_elements_by_xpath("//*[#id='aside']/fieldset/ul/li[2]")[0]
frame_button.click()
time.sleep(1)
#Switch iframe
driver.switch_to.frame(driver.find_element_by_xpath('//*[#id="the_iframe"]'))
driver.wait
driver.switch_to.frame(driver.find_element_by_xpath("//iframe[contains(#src,'mysafind')]"))
time.sleep(1)
#Insert instit.Name
CTNselect = Select(driver.find_element_by_css_selector('#sch_bub_nm'))
CTNselect.select_by_value(COURTNO)
#Insert Year
CYselect = Select(driver.find_element_by_css_selector('#sel_sa_year'))
CYselect.select_by_value(CaseYear)
#Insert Number
CBselect = Select(driver.find_element_by_css_selector('#sa_gubun'))
CBselect.select_by_visible_text(CaseBun)
#사건번호 입력 (숫자부분)
CS_Insert = WAIT.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#sa_serial")))
CS_Insert.click()
CS_Insert.clear()
CS_Insert.send_keys(CaseSerial)
#Insert Name
CN_Insert = WAIT.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#ds_nm")))
CN_Insert.click()
CN_Insert.clear()
CN_Insert.send_keys(ConsumerName)
break
ultrawait.until(condition)
Don't mind indention errors, problem of copy-paste.
I think its from #Switch iframe I have issue with.
Those inputs that come after #Switch iframe are all functional. I've tested them by opening iframe at another tab.
You need to deal with your frames separately:
When you finished working with one of them and want to switch to another -- you need to do:
driver.switch_to.default_content()
then switch to another one.
Better to use explicit wait for switching to the frame:
from selenium.webdriver.support import ui
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
ui.WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "#contants>iframe")))
wherein By you can use any locator.
As per your html structure, both the iframes are different and the second one is not in between the first one. It would have been inside the first one if the html structure was like:
<div>
<iframe1>
<iframe2>
</iframe2>
</iframe1>
</div>
But as your first <div> and first <iframe> are ending before starting the second div and iframe, it means both the iframes are seperate.
So, according to your requirements, you just need to switch to the second iframe which can be done using:
WebDriverWait(driver, 10).until(EC.frame_to_be_available_and_switch_to_it(By.CSS_SELECTOR,"second iframe css"))
Updated Answer:
Try the code:
driver.switch_to.frame(driver.find_element_by_xpath('//*[#id="the_iframe"]'))
driver.WAIT
driver.switch_to.frame(driver.find_element_by_xpath('//iframe[contains(#src,'mysafind')]'))
driver.WAIT
Related
i'm having a problem with my script in pyhton. Each time when the web page that im using opens the iframe src changes.
By.CSS_SELECTOR,"iframe#IFRAME_muVN"
(For example de code above is the current iframe when i copy with css selector)
But when i enter to the web page again the name of that iframe changes.
#IFRAME_6Eh8
is there a way to manage that change of the iframe, because im allways getting timeout due to the webdriver wait and the iframe element is never gonna be found.
this is my code:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from datetime import date
import time
s=Service(r'C:\Users\dbayona\Webdriver\chromedriver.exe')
driver = webdriver.Chrome(service = s)
driver.maximize_window()
driver.get('http://190.109.11.66:8888/BOE/BI')
iframe = driver.find_element(By.NAME, "servletBridgeIframe")
driver.switch_to.frame(iframe)
username = driver.find_element(By.XPATH, '//*[#id="_id0:logon:USERNAME"]')
username.send_keys("*****")
password = driver.find_element(By.XPATH, '//*[#id="_id0:logon:PASSWORD"]')
password.send_keys("*****")
login = driver.find_element(By.XPATH, '//*[#id="_id0:logon:logonButton"]')
login.click()
iframe =WebDriverWait(driver, 20).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#iframeHome-122668")))
driver.implicitly_wait(15)
dropdown = driver.find_element(By.XPATH, '//*[#id="header3_5"]')
dropdown.click()
storesense = driver.find_element(By.XPATH, '//*[#id="li_item_0_4_1"]')
driver.implicitly_wait(5)
storesense.click()
iframe = WebDriverWait(driver, 120).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#IFRAME_muVN")))
date = driver.find_element(By.XPATH, '//*[#id="date-picker"]')
today = date.today()
d1 = today.strftime("%d/%m/%Y")
date.send_keys(d1)
driver.switch_to.default_content()
Code where im trying to find the iframe:
iframe = WebDriverWait(driver, 120).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe#IFRAME_muVN")))
image of the iframe:
Iframe of the page
Since the element is dynamic try the following css selector. ^ means startswith
iframe = WebDriverWait(driver, 120).until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR,"iframe[id^='IFRAME_']")))
try to find by tag name <iframe> but make sure if you not have multiple tag name like this inside the element that its related to
My program checks a login page for available combinations. Upon first opening up the page, there is a "check availability" button, which has an ID which Selenium is able to find/use to click.
If the username is taken, a new button pops up which says "check another combination", however the DOM inspector only gives the following information about the second button:
<a class="btn btn-outline-primary btn-block mt-4" href="" role="button" data-ng-click="combination.reset()">
Check another combination
</a>
I have tried finding this button by CLASS, CLASSNAME, copying and pasting the XPATH from the inspector and all these have lead to not only the button clicking not working, but the entering and submitting of the intial combination also ceasing to work.
Hoping someone can suggest how to identify this button from the given information. For reference, here is one of the lines I tried:
check_another_combo_button = driver.find_element(By.CLASS, "btn btn-outline-primary btn-block mt-4")
Here is my full code:
from selenium import webdriver
from selenium.webdriver.common.by import By
from webdriver_manager.firefox import GeckoDriverManager
import time
driver = webdriver.Firefox(executable_path=GeckoDriverManager().install())
driver.maximize_window()
site = "https://www......"
driver.get(site)
combination_input_field = driver.find_element(By.ID, "userCombination")
check_availability_button = driver.find_element(By.ID, "btn_fQPAC_submit")
combination_input_field.send_keys(77777) #77777 is one of the unavailable combos
check_availability_button.click()
time.sleep(2)
check_another_combo_button = driver.find_element(By.CLASS_NAME, "btn btn-outline-primary btn-block mt-4")
check_another_combo_button.click()
I suspect you want to check for inputs say inputs in a loop. Here is the solution using both chrome and firefox.
Solution using chrome driver :
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.ui import WebDriverWait
chrome_path = r"C:\Users\hpoddar\Desktop\Tools\chromedriver_win32\chromedriver.exe"
s = Service(chrome_path)
url = 'https://www......'
driver = webdriver.Chrome(service=s)
driver.get(url)
inputs = ['77777', '88888', '99999', '11111']
for plate in inputs:
combination_input_field = driver.find_element(By.ID, "qPlateCombination")
check_availability_button = driver.find_element(By.ID, "btn_fQPAC_submit")
combination_input_field.send_keys(plate)
check_availability_button.click()
element = WebDriverWait(driver, 10).until(EC.visibility_of_element_located((By.CSS_SELECTOR, ".btn.btn-outline-primary.btn-block.mt-4")))
check_another_combo_button = driver.find_element(By.CSS_SELECTOR, ".btn.btn-outline-primary.btn-block.mt-4")
check_another_combo_button.click()
Solution using Geckodriver :
To use Geckodriver, all you need to add is
from webdriver_manager.firefox import GeckoDriverManager
from selenium.webdriver.chrome.service import Service
and change driver initialization line to
s = Service(executable_path=GeckoDriverManager().install())
webdriver.Firefox(service=s)
driver.maximize_window()
when you have common classes or dynamically generated classes for elements you wish to interact, the next approach is to be fixed by text.
Try with xpath, that matches the text:
//a[normalize-space(.)='Check another combination']
normalize-space(.) - will trim the whitespace and match the text inside the element.
Yu can include #role="button" as additional matcher inside the a tag.
The link inside the href is constantly changing but the xpath of this href is always the same.
How can I click on the www.confirmationemail.com ?
<div dir="ltr">
<p>exampleTEXT.</p>
<p>www.confirmationemail.com</p>
<p>exampleTEXT.</p>
<p>exampleTEXT,</p>
<p>exampleTEXT</p>
</div>
This is the page I'm working on:https://www.minuteinbox.com/
The process is as follows: registering on a site with the e-mail received from here and receiving an e-mail, logging in to the e-mail, but I cannot click on the link in its content.
from selenium import webdriver
from time import sleep
import config2 as cf
from selenium.webdriver.support.select import Select
import selenium.webdriver.support.ui as ui
from selenium.webdriver.common.keys import Keys
from asyncio import sleep
import time
driver = webdriver.Chrome("C:\\ChromeDriver\\chromedriver.exe")
url = "https://www.minuteinbox.com/"
url2 = "EXAMPLE.COM"
driver.get(url)
element = driver.find_element_by_xpath("XPATH").text
print(element)
time.sleep(4)
driver.execute_script("window.open('');")
driver.switch_to.window(driver.window_handles[1])
driver.get(url2)
sec = driver.find_element_by_xpath("XPATH")
sec.click()
devam = driver.find_element_by_xpath("XPATH")
devam.click()
ad = driver.find_element_by_xpath("XPATH")
ad.send_keys("deneme")
soyad = driver.find_element_by_xpath("XPATH")
soyad.send_keys("test")
eMail = driver.find_element_by_css_selector("#user_email")
eMail.send_keys(element)
eMail2 = driver.find_element_by_css_selector("#user_email_confirmation")
eMail2.send_keys(element)
sifre = driver.find_element_by_css_selector("#user_password")
sifre.send_keys("PASS")
sifre2 = driver.find_element_by_css_selector("#user_password_confirmation")
sifre2.send_keys("PASS")
buton = driver.find_element_by_css_selector("SELECT")
buton.click()
hesapol = driver.find_element_by_css_selector("SELECT")
hesapol.click()
sleep(2)
driver.switch_to.window(driver.window_handles[0])
time.sleep(7)
bas = driver.find_element_by_css_selector("#schranka > tr:nth-child(1)")
bas.click()
time.sleep(1)
time.sleep(1)
SD = driver.switch_to.frame(driver.find_element_by_css_selector("iframe#iframeMail"))
time.sleep(5)
SD = driver.find_element_by_xpath("//a[contains(#href,'minuteinbox')]").click
driver.switch_to.default_content()
sd = I put this just to be able to write it in the code section
SOLVED
İMPORTS
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
bas = driver.find_element_by_css_selector("#schranka > tr:nth-child(1)")
bas.click()
time.sleep(3)
wait = WebDriverWait(driver, 10)
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[id='iframeMail']")))
print(driver.page_source)
link = driver.find_element_by_xpath("/html/body/div/p[2]/a")
link.click()
As you mentioned, the XPath of that element is constant.
So you can get that element based the constant XPath locator and click it.
Something like this:
driver.find_element_by_xpath('the_constant_xpath').click()
UPD
The element you want to be clicked can be located by XPath.
However, it is inside an iframe, so in order to access it you will have to switch to that iframe first.
I have also made your locators better.
So your code could be something like this:
driver.switch_to.window(driver.window_handles[0])
time.sleep(5)
bas = driver.find_element_by_css_selector("td.from")
bas.click()
time.sleep(1)
driver.switch_to.frame(driver.find_element_by_css_selector("iframe#iframeMail"))
driver.find_element_by_xpath("//a[contains(#href,'minuteinbox')]").click
When you finished working inside the iframe you will have to get out to the default content with
driver.switch_to.default_content()
i basically want to click every load more button thats on the page before running the rest of my code because otherwise i wont be able to access each profile.
There are 2 Problems:
first how do i even access it? i tried similar methods to the fancyCompLabel part of my code but it wont work.
second im not sure how i should loop through all buttons since i would assume the second button only starts loading until the first one is clicked.
heres the relevant html part and a picture of the button
<span type="button" class="md-text-button button-orange-white" onclick="loadFollowing();">mehr anzeigen</span>
Heres the code to access each profile but as you can see it only runs until the first load button.
from bs4 import BeautifulSoup
import time
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.support.wait import WebDriverWait
time.sleep(3)
# Set some Selenium Options
options = webdriver.ChromeOptions()
# options.add_argument('--headless')
options.add_argument('--no-sandbox')
options.add_argument('--disable-dev-shm-usage')
# Webdriver
wd = webdriver.Chrome(executable_path='/usr/bin/chromedriver', options=options)
# URL
url = 'https://www.techpilot.de/zulieferer-suchen?laserschneiden%202d%20(laserstrahlschneiden)'
# Load URL
wd.get(url)
# Get HTML
soup = BeautifulSoup(wd.page_source, 'html.parser')
wait = WebDriverWait(wd, 15)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#bodyJSP #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll"))).click()
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "#efficientSearchIframe")))
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, ".hideFunctionalScrollbar #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll"))).click()
#wd.switch_to.default_content() # you do not need to switch to default content because iframe is closed already
wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".fancyCompLabel")))
results = wd.find_elements_by_css_selector(".fancyCompLabel")
for profil in results:
print(profil.text) #heres the rest of my code but its not relevant
wd.close()
As I see the second pop-up element located by .hideFunctionalScrollbar #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll is initially appearing out of the visible screen.
So after switching to the iframe you need to scroll to that element before trying to click on it.
Also, presence_of_all_elements_located doesn't actually wait for all the elements presence. It even doesn't know how many such elements will be. It returns once it finds at least 1 element matching the passed locator.
So I'd advice to add a short sleep after that line to allow all those elements to be actually loaded.
from selenium.webdriver.common.action_chains import ActionChains
wait = WebDriverWait(wd, 15)
actions = ActionChains(wd)
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "#bodyJSP #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll"))).click()
wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "#efficientSearchIframe")))
second_pop_up = wd.find_element_by_css(".hideFunctionalScrollbar #CybotCookiebotDialogBodyLevelButtonLevelOptinAllowAll")
actions.move_to_element(second_pop_up).build().perform()
time.sleep(0.5)
second_pop_up.click()
wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, ".fancyCompLabel")))
time.sleep(0.5)
for profil in results:
print(profil.text) #heres the rest of my code but its not relevant
wd.close()
from selenium import webdriver
import time
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver import ActionChains
PATH = "C:\Program Files (x86)\chromedriver.exe"
driver = webdriver.Chrome(PATH)
driver.maximize_window()
driver.get("https://accounts.ebuyer.com/customer/account/index.html?action=bG9naW4=")
title = driver.find_element_by_name("email")
title.clear()
title.send_keys("johnsmith#gmail.com")
password = driver.find_element_by_id("password")
password.send_keys("pass123")
driver.find_element_by_xpath('//*[#id="login"]/div[4]/input').click()
driver.find_element_by_xpath('/html/body/div[3]/div/button[2]').click()
#accepts cookies
driver.get("https://www.ebuyer.com/search?q=graphics+cards")
WebDriverWait(driver, 10)
try:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH,'//*[#id="grid-view"]/div[1]/div[4]/button'))
) #finds add to basket button
element.click()
driver.find_element_by_xpath('/html/body/header/div/div[3]/div/a[1]').click()
print("IN BASKET")
#adds to basket if found
except:
element = WebDriverWait(driver, 5).until(
EC.presence_of_element_located((By.XPATH,'//*[#id="main-
content"]/div/div[1]/div[2]/div[2]/div/div[2]/ul/li[2]/a'))
)
element.click()
#moves to next page
this is what I'm trying to click but the id changes on each product grid.
<button class="button button--mini-basket button--small js-add-to-mini-basket" data-product-
id="798879" data-ajax-basket-url="https://orders.ebuyer.com/customer/products/index.html?
action=YWpheF9jYXJ0X2FkZF9pdGVt" data-analytics-event="click" data-event-category="Search Listings - Grid" data-event-action="Product Click" data-event-label="Add to Basket Button">Add to
Basket</button>
I want to take <button class="button button--mini-basket button--small js-add-to-mini-basket" and
use this instead of By.XPATH,'//*[#id="grid-view"]/div[1]/div[4]/button'
I'm trying to scan the full page to find the Add to Basket Button and if it can't find that then it
will move on to the next page and repeat until it is found.
I have just built my first pc and I cannot get a graphics card anywhere so I want to use this grab
one.
I've recently found a love for coding so I'm quite new to this, I hope I've explained myself properly
and any help would be appreciated.
Use following xpath to identify. Use element_to_be_clickable() instead presence_of_element_located()
element =WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH,"//button[text()='Add to Basket']"))
Try following xpath
//button[#class='button button--mini-basket button--small js-add-to-mini-basket' and contains(text(),'Add to Basket')]