Code at Selenium by python
from selenium import webdriver
from selenium.webdriver.support.select import Select
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.action_chains import ActionChains
driver = webdriver.Chrome()
driver.maximize_window()
driver.get("https://motul.lubricantadvisor.com/Default.aspx?data=1&lang=ENG&lang=eng")
def getallcars():
wait = WebDriverWait(driver, 10)
wait.until(EC.presence_of_element_located((By.ID, "ctl00_ContentPlaceHolder1_rptCategoryBtn_ctl01_btnImage")))
driver.find_element(By.ID, "ctl00_ContentPlaceHolder1_rptCategoryBtn_ctl01_btnImage").click()
wait.until(EC.presence_of_element_located((By.ID, "ctl00_ContentPlaceHolder1_lblSelectedMake")))
driver.find_element(By.ID, 'ctl00_ContentPlaceHolder1_lblSelectedMake').click()
wait.until(EC.presence_of_element_located((By.CSS_SELECTOR, "#ctl00_ContentPlaceHolder1_lstMake")))
el = driver.find_element(By.NAME,"ctl00$ContentPlaceHolder1$lstMake")
car =[]
for option in el.find_elements(By.TAG_NAME,'option'):
car.append((option.text).encode('utf8'))
return car
cars=getallcars()
for value in cars:
drop = driver.find_element(By.CSS_SELECTOR, '#ctl00_ContentPlaceHolder1_lstMake')
sel = Select(drop)
sel.select_by_visible_text(value)
time.sleep(2) #<---- THIS POINT!!
driver.find_element(By.ID,'ctl00_ContentPlaceHolder1_HeaderModel').click()
el2 = driver.find_element(By.NAME, "ctl00$ContentPlaceHolder1$lstModel")
print "The models for %s are:" %value
for option in el2.find_elements(By.TAG_NAME,'option'):
print option.text
action = ActionChains(driver)
action.move_to_element_with_offset(el2, 300, 200)
action.click()
action.perform()
driver.find_element(By.CSS_SELECTOR,'#ctl00_ContentPlaceHolder1_HeaderMake').click()
I have been make the crawler. I don't understand completely yet. so I have a question. maybe It's 34line at code. I was mark about #
it's use be the "time.sleep(2)" method. because It didn't detect the select box when It's change about "sel.select_by_visible_text(value)"
how can I do that? I don't want to use the "time.sleep(2)"method.
already I tried "expected_conditions.presence_of_element_located" It doesn't work. I guess It's problem about dropbox. this size is not basically because It did well when I tried another size tried "expected_conditions.presence_of_element_located"
Explicit wait will not work, because the conditions you can use are "element to be clickable", "element to be visible" and like that.
The element that you using for explicit wait is available and clickable also, but its failing because other element is overlapping it.
Since the other element's overlap takes time to disappear, we have to wait for the overlap to disappear before we can click on the element.
Explicit wait can wait for element to appear and clickable, which it is already is but it is being hidden by other element.
In this scenario, we have to use time.sleep() to put a hard wait
Related
The following code is not writing any partial string in the From input field on the website even though this element seems to be an active element.
I spent lot of time trying to debug and make the code work but no success. Can anyone please provide some hint on what is wrong. Thanks.
from selenium import webdriver
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.keys import Keys
from colorama import init, Fore
class BookingTest1():
def __init__(self):
pass
def test1(self):
baseUrl="https://www.goibibo.com/"
driver=webdriver.Chrome()
driver.maximize_window()
#open airline site
driver.get(baseUrl)
driver.implicitly_wait(3)
# Enter origin location.
partialTextOrigin="New"
#select flight tab
driver. find_element(By.XPATH,"//ul[#class='happy-nav']//li//a[#href='/flights/']").click()
# select input box
textElement = driver.find_element(By.XPATH, "//input")
# check if input box is active
if textElement==driver.switch_to.active_element:
print('element is in focus')
textElement.send_keys(partialTextOrigin)
else:
print('element is not in focus')
print("Focus Event Triggered")
driver.execute_script("arguments[0].focus();", textElement)
time.sleep(5)
if textElement==driver.switch_to.active_element:
print('finally element is in focus')
print(partialTextOrigin)
textElement.send_keys(partialTextOrigin)
time.sleep(5)
#test the code
tst=BookingTest1()
tst.test1()
There are several issues here:
First you need to click on p element in the From block and only after that when input appears there you can insert the text to it.
You should use unique locators. (There more that 10 input elements on this page)
Using WebDriverWait expected conditions explicit waits are much better than implicitly_wait in most cases.
No need to set timeouts to too short values.
No need to use driver.switch_to.active_element here.
The following code works for me:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By
from selenium.webdriver.support import expected_conditions as EC
options = Options()
options.add_argument("start-maximized")
webdriver_service = Service('C:\webdrivers\chromedriver.exe')
driver = webdriver.Chrome(service=webdriver_service, options=options)
url = "https://www.goibibo.com/"
flights_xpath = "//ul[#class='happy-nav']//li//a[#href='/flights/']"
from_xpath = "//div[./span[contains(.,'From')]]//p[contains(text(),'Enter city')]"
from_input_xpath = "//div[./span[contains(.,'From')]]//input"
partialTextOrigin = "New"
wait = WebDriverWait(driver, 10)
driver.get(url)
wait.until(EC.element_to_be_clickable((By.XPATH, flights_xpath))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, from_xpath))).click()
wait.until(EC.element_to_be_clickable((By.XPATH, from_input_xpath))).send_keys(partialTextOrigin)
from_xpath and from_input_xpath XPath locators are a little complex.
I was not sure about the class names in that elements block if they are fixed so I based on the texts.
For example "//div[./span[contains(.,'From')]]//p[contains(text(),'Enter city')]" means:
Find such div that it has a direct span child so that span contains From text content.
From the div parent element above find inside it a p child that contains Enter city text.
Similarly to the above locator "//div[./span[contains(.,'From')]]//input" means: find parent div as described before, then find inside it an input child element.
The result of the code above is
I am trying to get all players from this Page:
https://earthmc.net/map
(You can see them when you click on the arrow on the right side).
The tags for the players looks like this:Blu_Viper
I am using this code for this:
driver = webdriver.Firefox()
driver.get("https://earthmc.net/map/")
name = driver.find_elements_by_xpath('//a[#title="Center on player"]')
for i in range(len(name)):
print(name[i].text)
driver.close()
The driver finds the Xpath but it prints only a blank string.
How can I fix this?
You can use this code:- Moreover, you can change the sleep timing as per your need. for your information, this code gives error sometimes because the list is pretty dynamic. But you can run it again to get the full player list.
from selenium import webdriver
from selenium.webdriver import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
driver = webdriver.Chrome()
action = ActionChains(driver)
driver.get('https://earthmc.net/map/')
wait = WebDriverWait(driver, 20)
time.sleep(20)
ExpandArrow = wait.until(EC.visibility_of_element_located((By.XPATH, '//div[#class="hitbar"]')))
action.move_to_element(ExpandArrow).perform()
PlayerList = driver.find_elements_by_xpath('//li[contains(#class,"player")]')
for element in PlayerList:
driver.execute_script("arguments[0].scrollIntoView();", element)
print(element.text)
print("Successfully Completed.")
Note - If this is what you are looking for then mark this as the answer.
I'm designing a web scraper. At a few points I need it to wait for around 10 seconds before jumping to the next action to account for internet connection problems. I want to have a simple implicit wait.
driver.get('MY WEBSITE')
driver.implicitly_wait(10)
menu = driver.find_element_by_link_text("Export")
menu2 = driver.find_element_by_xpath('//td[text()="Data"]')
actions = ActionChains(driver)
actions.move_to_element(menu)
actions.click(menu)
actions.move_to_element(menu2)
actions.click(menu2)
actions.perform()
The only problem is: it's not waiting. I've even tried putting 20 and more secs as the implicitly_wait parameter in order to be completely sure and there was no change. It's opening the website and going directly to search for the two elements. Can anyone explain that please?
From the docs:
An implicit wait tells WebDriver to poll the DOM for a certain amount of time when trying to find any element (or elements) not immediately available. The default setting is 0. Once set, the implicit wait is set for the life of the WebDriver object.
So if the element is immediately available, it won't wait.
Try to use WebDriverWait :
E.g
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
driver = webdriver.Firefox()
driver.get("http://somedomain/url_that_delays_loading")
try:
element = WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.ID, "myDynamicElement"))
)
finally:
driver.quit()
I want to click on button on web site, but this button appears after you put your cursor on the right place, otherwise you can not see this button. I tried to ignore that and do just normal click by finding the element by xpath. But that did not work out, there was mistake:
selenium.common.exceptions.ElementNotInteractableException: Message: element not
interactable: element has zero size
How to deal with that?
To hover over the element you can use something like this:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
chrome= webdriver.Chrome()
chrome.get('http://foo.bar')
element = chrome.find_element_by_css_selector("the_element_u_want")
hover = ActionChains(chrome).move_to_element(element)
hover.perform()
if the element takes time to appear use selenium's wait or time.sleep()
find more info about ActionChains here
this is some code I found here.
Usually, the ElementNotInteractableException is thrown when the element hasn't loaded completely. Here's a possible solution:
from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as ec
driver = webdriver.Chrome('C:\\Users\\dell\\Libs\\chromedriver.exe')
driver.get("http://url")
driver.maximize_window()
# wait for element to appear, then hover it
wait = WebDriverWait(driver, 10)
men_menu = wait.until(ec.visibility_of_element_located((By.XPATH, "//a[#data-tracking-id='men']")))
ActionChains(driver).move_to_element(men_menu).perform()
This method worked well for me.
def hoverXPATH(xpath):
item = WebDriverWait(driver, 10)\
.until(EC.visibility_of_element_located((By.XPATH, xpath)))
ActionChains(driver).move_to_element(item).perform()
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
url = 'https://www.msha.gov/mine-data-retrieval-system'
driver = webdriver.Chrome(executable_path='chromedriver')
driver.get(url)
#driver.find_element_by_xpath('//*[#id="mstr90"]/div[1]/div/div') error
#driver.find_elements_by_xpath('//input') gives 3 while in driver gives 10
I am unable to find element where the input "Search by Mine ID by typing here.." is, the document is fully loaded but it can't locate it. What I want to do is simply pass in an input "0100003" then submit
Iframe is present on your page. Before you interact with inputbox you need to switch on to iframee. Refer below code to resolve your issue.
wait = WebDriverWait(driver, 10)
driver.get("https://www.msha.gov/mine-data-retrieval-system")
driver.switch_to.frame("iframe1")
wait = WebDriverWait(driver, 10)
inputBox = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[#class='mstrmojo-SimpleObjectInputBox-empty']"))).click()
inputBox1 = wait.until(EC.element_to_be_clickable((By.XPATH, "//div[#class='mstrmojo-SimpleObjectInputBox-container mstrmojo-scrollNode']//input")))
inputBox1.send_keys("0100003")
Updated Code to handle dropdown
wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "div#mstr100,mstrmojo-Popup.mstrmojo.SearchBoxSelector-suggest"))).click()
Note: please add below imports to your solution
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
Output:
The element you are trying to find is inside an iframe, so you will need to switch to that iframe first and then do your find element. Also, it's a best practice to use waits to give pages/elements time to load before a find element timeouts and throws an error.
iframe = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#iframe1')))
driver.switch_to.frame(iframe)
mine_id = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.XPATH, '//*[#id="mstr90"]/div[1]/div/div')))
Then you need to click this element to make it interactable.
mine_id.click()
Once you click then you need to re-find the input box before sending keys.
mine_id_input = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mstr90 input')))
mine_id_input.send_keys('0100003')
To select the suggestion displayed:
suggestion = WebDriverWait(driver, 15).until(EC.presence_of_element_located((By.CSS_SELECTOR, '#mstr100')))
suggestion.click()
if you wanted to continue on interacting outside the iframe after this is done, you will want to switch back out of the iframe like this:
driver.switch_to.default_content()