Not able to click on elements in a dropdown menu using selenium - python

I'm trying to create an automated web session where I log onto a website and select an option from a dropdown menu. I'm able to get to the page using selenium but I'm unable to click on the bar with opens a drop down menu and then select the option I want. Here is a screenshot of the page and it's HTML Code:
[![enter image description here][1]][1]
[![enter image description here][2]][2]
I would like to click on the 'Degraded Performance' option from the dropdown. I'm a bit stuck here because the HTML of the dropdown does not resemble [this one][3] at all (no way to 'select'). I've also tried watching YouTube videos to no success :(. Here is the script I'm running:
#login to status page if server status is not 'Ok'
driver = webdriver.Safari()
wait = WebDriverWait(driver, 20)
driver.get('https://manage.statuspage.io/login')
email = wait.until(EC.visibility_of_element_located((By.ID, "email")))
email.clear()
email.send_keys(user)
wait.until(EC.visibility_of_element_located((By.ID, "login-btn"))).click()
wait.until(EC.visibility_of_element_located((By.ID, "login-submit"))).click()
password = wait.until(EC.visibility_of_element_located((By.ID, "password")))
password.clear()
password.send_keys(passw)
driver.find_element_by_id('login-submit').click()
#Go to correct component
wait.until(EC.visibility_of_element_located((By.LINK_TEXT, "Components"))).click()
driver.get('https://manage.statuspage.io/pages/hfxvt9zqtn8m/components/g39hxh3gq0bc/edit')
#Change status
wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "status-dropdown__value-container status-dropdown__value-container--has-value css-1b6odlt"))).click()
#here click on 'degraded performance'
#save
driver.find_element_by_id('btn-save-component').click()
The line ```wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "status-dropdown__value-container status-dropdown__value-container--has-value css-1b6odlt"))).click()``` returns a timeout exception.
Any help would be really great!
HTML in text format:
<div class="status-dropdown__control css-4avucx-control"><div class="status-dropdown__value-container status-dropdown__value-container--has-value css-1b6odlt"><div class="status-dropdown__single-value css-lrg2au-singleValue" style="opacity: 1; transition: opacity 1ms;"><div class="_2cgnn8jOgeTLsVfOQFh5Rs"><i class="component-status page-colors text-color degraded_performance"></i><span style="padding-left: 8px; padding-bottom: 0px;">Degraded performance</span></div></div><input id="react-select-2-input" readonly="" tabindex="0" class="css-62g3xt-dummyInput" value=""></div><div class="status-dropdown__indicators css-t5ibhw"><div aria-hidden="true" class="status-dropdown__indicator status-dropdown__dropdown-indicator css-gg6ksl-indicatorContainer"><span role="img" aria-label="open" class="css-rq2oqu"><svg width="24" height="24" viewBox="0 0 24 24" role="presentation"><path d="M8.292 10.293a1.009 1.009 0 000 1.419l2.939 2.965c.218.215.5.322.779.322s.556-.107.769-.322l2.93-2.955a1.01 1.01 0 000-1.419.987.987 0 00-1.406 0l-2.298 2.317-2.307-2.327a.99.99 0 00-1.406 0z" fill="currentColor" fill-rule="evenodd"></path></svg></span></div></div></div>
[1]: https://i.stack.imgur.com/62NnJ.png
[2]: https://i.stack.imgur.com/zMbo0.png
[3]: https://stackoverflow.com/questions/7867537/how-to-select-a-drop-down-menu-value-with-selenium-using-python

See you can not use Select from Selenium since that is meant for drop down built using Select and option tag.
instead I would suggest you to click on Degraded Performance directly.
driver.find_element_by_xpath("//span[contains(text(),'Degraded Performance')]").click()
also I think first you will need to click on drop down bar, then the above code should work, probably will have to use Explicit wait as well.
Update 1 :
instead of
wait.until(EC.visibility_of_element_located((By.CLASS_NAME, "status-dropdown__value-container status-dropdown__value-container--has-value css-1b6odlt"))).click()
try this :
wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "div[class^='status-dropdown__single-value']+input"))).click()

Related

finding correct input tag to upload a image on instagram

i am trying to upload a image to instagram using Python and Selenium...
I need to emulate a phone and pass the image in a input tag, it works, because I can upload a profile picture, but the only problem is, that I cant find the correct input tag for uploading a image to my feed.
The only one i found was the one for uploading a new profile picture.
Could you please help me to find the input tag?
Here is the code im using:
def upload(self, image, text):
driver.get("https://www.instagram.com/")
#find input field
upload_btn = driver.find_element(By.XPATH, "needed xpath")
time.sleep(2)
#send image
upload_btn.send_keys("C:\\Users\\brend\PycharmProjects\ClimateCoinBot\\PP2.jpg") #full path of the file which is to be uploaded
Would be cool, if you could help me :)
The element to upload file with .send_keys() method can normally be located with the following locator:
upload_btn = driver.find_element(By.XPATH, "//input[#type='file']")
You should add a wait / delay after
driver.get("https://www.instagram.com/")
before
upload_btn = driver.find_element(By.XPATH, "needed xpath")
to make the page fully loaded before accessing this element.
So your code can be something like this:
def upload(self, image, text):
driver.get("https://www.instagram.com/")
time.sleep(2)
#find input field
upload_btn = driver.find_element(By.XPATH, "//input[#type='file']")
#send image
upload_btn.send_keys("C:\\Users\\brend\PycharmProjects\ClimateCoinBot\\PP2.jpg")
But it is recommended to use explicit wait rather than hardcoded pauses.
So, I'm working in a instagram script with Selenium, and I'm in troubles like you. But I've found the code you're looking for. Take a look:
That's the story (send photo) code:
<button class="JdY43"> <span class="ctM9u _2dbep " role="link" tabindex="-1" style="width: 56px; height: 56px;">
<img alt="" class="_6q-tv" crossorigin="anonymous" data-testid="user-avatar" draggable="false" src="https://instagram.fgig4-1.fna.fbcdn.net/v/t51.2885-19/s150x150/271673104_907632683286365_8637941351902776951_n.jpg?_nc_ht=instagram.fgig4-.fna.fbcdn.net&_nc_cat=105&_nc_ohc=nZGpq1e3_awAX_pI_zX&edm=AIQHJ4wBAAAA&ccb=7-4&oh=00_AT-nr4lxSToGQqIQCitUKJQhDXaMCePqmSxEy77CzjlTjA&oe=6212095C&_nc_sid=7b02f1"></span>
<div class="XdXBI">Seu story</div> <div class="TiuNS">
<svg aria-label="Ícone de mais" class="_8-yf5 " color="#0095f6" fill="#0095f6" height="16" role="img" viewBox="0 0 24 24" width="16">
<path d="M12.001.504a11.5 11.5 0 1011.5 11.5 11.513 11.513 0 00-11.5-11.5zm5 12.5h-4v4a1 1 0 01-2 0v-4h-4a1 1 0 110-2h4v-4a1 1 0 112 0v4h4a1 1 0 010 2z">
</path></svg></div>
<form enctype="multipart/form-data" method="POST" role="presentation"><!-- look here -->
<input accept="image/jpeg" class="tb_sK" type="file"></form></button><!-- look here -->
Actually Instagram page have athe following structure:
Button Tag > (a lot of non important things) > form > input> (close button tag)
It's a smart way to hide the photo input. I waste too many hours searching for it.
So, you need to know: There is 4 input tags like as the listed above. You'll probably need to select them using a XPATH ilke:
//*[#id="react-root"]/section/main/section/div[1]/div[2]/div/div/div/button/form/input
That, is the first problem. The second one is that input is with display attibute setted like "none!important". You can inject javaScript in console to fix it(I did and it and turned it in "inline").
But, I can't continue from this point, because when I send the file path to the input nothing happens.
So, if instead of just send the path, I use ".submit()" after send_keys I get the following message:
"This page could not be loaded.
If cookies are active in your browser or it
is in Private, try enabling cookies or deactivate
Private Mode and perform the action again."
That's everything that I have. I can upload photos using Selenium + Pyautogui, I've a script with it, and I use it when the time to click the button and set the path comes. But it's not usefull if you are in your own computer, it writes in other windows, if it's selected. We can talk about it, if you want. Although I'd this solution I really want a full selenium script.
I want to contribute to you research, so I would love if you answer if it worked for you, or contributed to you job, 'cause I want to keep building my bot. :)

Validating Pin-Pad form using Selenium Python

I am trying to input code on a pin pad form available on a website and get it validated. However, I am getting a validation error. I fear the clicked pin buttons are not being read by the website's script. Can anyone help me with this? I am attaching the code as well as the page source code.
The UI of website looks like this
The div class on website which contains the keypad is as follows:-
<div class="pin_pad">
<span id='keypad1' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">1</span>
<span id='keypad2' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">2</span>
<span id='keypad3' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">3</span>
<span id='keypad4' onmouseout="this.className=''" onmouseover="this.className='pin_hover'">4</span>
<span class="submit_btn" onmouseout="this.className='submit_btn'" onmouseover="this.className='submit_btnpin_hover'" onclick="return validate();">Submit</span>
</div>
My pin is "4444". I am trying to use the .click() method to get "4" clicked. Although I can see that "4" has been clicked 4 times, upon submit, the page shows a validation error. Can anyone help me in solving this problem? Here's my code in python:-
pinpad = driver.find_elements_by_class_name('pin_pad')
element = driver.find_element_by_xpath("//span[text()=4]").click()
for k in range(4):
actionChains = ActionChains(driver)
actionChains.context_click(element).perform()
time.sleep(1)
driver.find_element_by_xpath("//span[text()='Submit']").submit()
Instead of
context_click(element).perform()
do this :
move_to_element(key4).click().perform()
context_click is for right click and move_to_element() is for moving your mouse cursor to the specify element.
Brief explanation :
You can introduce WebDriverWait for more stability, and I don't think you need to do context_click() instead it is move_to_element() plus ActionChains object creation optimization and instead of submit you may wanna use click(). Check out the code below :
pinpad = driver.find_elements_by_class_name('pin_pad')
key4 = wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, "span#keypad4"))).click()
actionChains = ActionChains(driver)
for k in range(4):
actionChains.move_to_element(key4).click().perform()
sleep(1)
wait.until(EC.element_to_be_clickable((By.XPATH, "//span[text()='Submit']"))).click()

How to find and click on HTML image element

I'm new with Selenium and struggle with this one for few hours.
I have an HTML page that contains icon and stream view (both images), the browser view is on 100% and I would like to modify it and make it smaller,
it can be done by changing browser zoom, modifying CSS property or clicking on the image.
My code starts with open browser and waits till all elements load:
driver = webdriver.Firefox()
driver.get('http://' + user +':'+password+'#'+camera_address)
driver.maximize_window()
driver.implicitly_wait(15) # seconds
I tried to do so via zoom:
driver.execute_script("document.body.style.zoom='0.4'")
Didn't worked.
Tried to do it via Selenium -- find element and change CSS:
myDynamicElement = driver.find_elements_by_id("stream")
or find the image and click it with:
driver.find_element_by_xpath('//img[#src="../pics/button_downsize_27x27px.gif"]').click()
or
driver.find_elements_by_xpath('//*[#img]').click()
or
driver.find_elements_by_tag_name('img').click()
The HTML page looks like this:
<img src="/pics/button_downsize_27x27px.gif" width="27" height="27" border="0" title="Scale down to 800 px width" alt="Scale down to 800 px width">
<td colspan="3" align="center"><img id="stream" src="/mjpg/video.mjpg" width="2560" height="1920" border="0" alt="If no image is displayed, there might be too many viewers, or the browser configuration may have to be changed. See help for detailed instructions on how to do this."><br></td>
Tried with #title and #alt and even contain but nothing works.
What am I doing wrong?!?! How to find and click on this image (/pics/button_downsize_27x27px.gif)?
To click on your desired image -- please use the reference code mentioned here.
new WebDriverWait(driver, 10).until(ExpectedConditions.visibilityOfAllElementsLocatedBy((By.cssSelector("a"))));
List<WebElement> elem = driver.findElements(By.tagName("a"));
for(WebElement el : elem){
String element = el.getAttribute("src");
if(element.contains("/pics/button_downsize_27x27px.gif")){
el.click();
break;
}
}
It is in Java, you can implement it in Python.
Thank you all, finally, I did a little workaround since I saw that in chrome there is a little bug and via Firefox, I cannot find the element.
So I retrieve again the URL after all elements loaded and modify it so the JavaScript function will be triggered:
myElem = WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.NAME, 'indexMain')))
driver.get(driver.current_url+'&size=8')
Thank you all for trying, this one was a challenge since the element have no id/name/class/css and the browser could not find the XPath.

Python selenium retrieve instagram followers

I'm trying to get the list of followers from my account using a code like this using selenium (after authentication with username and pwd):
driver.get("https://www.instagram.com/{0}/".format(account))
# Click the 'Follower(s)' link
r=driver.find_element_by_partial_link_text("follower").click()
print r
# Wait for the followers modal to load
xpath = "//div[#style='position: relative; z-index: 1;']/div/div[2]/div/div[1]"
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, xpath)))
# You'll need to figure out some scrolling magic here. Something that can
# scroll to the bottom of the followers modal, and know when its reached
# the bottom. This is pretty impractical for people with a lot of followers
# Finally, scrape the followers
xpath = "//div[#style='position: relative; z-index: 1;']//ul/li/div/div/div/div/a"
followers_elems = driver.find_elements_by_xpath(xpath)
the problem is the variable 'r' is 'None'. Is there a problem accessing your own followers?
Click method returns nothing, so…r is none

Selenium python click button

I just can't make the button click and go the the next page. I tried the following so far
<div class="step__footer">
<button class="step__footer__continue-btn btn " type="submit" name="button">
<span class="btn__content">Continue to payment method</span>
<i class="btn__spinner icon icon--button-spinner"></i>
</button>
<a class="step__footer__previous-link" href="https://checkout.shopify.com/946304/checkouts/1b6e3391268707abb18850300b89e59?step=contact_information">
<svg class="previous-link__icon icon--chevron icon" viewBox="0 0 6.7 11.3" height="11.3" width="6.7" xmlns="http://www.w3.org/2000/svg">
Return to customer information
</a>
</div>
driver = webdriver.Firefox()
driver.implicitly_wait(1) # seconds
driver.find_element_by_css_selector("step__footer__continue-btn btn").click()
driver.implicitly_wait(1) # seconds
driver.find_element_by_xpath("/html/body/div[2]/div/div[2]/div[2]/div/form/div[2]/button").click()
driver.implicitly_wait(1) # seconds
driver.find_element_by_name("button").click()
driver.implicitly_wait(1) # seconds
elem.send_keys(Keys.RETURN)
driver.implicitly_wait(1) # seconds
driver.find_element_by_css_selector("div.step__footer>button").click()
driver.implicitly_wait(1) # seconds
driver.find_element_by_css_selector("html.multi-step.mac.firefox.desktop.page--no-banner.page--logo-main.page--show.js.flexbox.flexboxlegacy.rgba.multiplebgs.boxshadow.opacity.cssanimations.csstransitions.generatedcontent.svg.inlinesvg.cors.boxsizing.display-table.pointerevents.placeholder.mediaqueries.floating-labels body div.content div.wrap div.main div.main__content div.step form.edit_checkout.animate-floating-labels div.step__footer button.step__footer__continue-btn.btn").click()
driver.implicitly_wait(1) # seconds
driver.find_element_by_link_text("Continue to payment method").click()
driver.implicitly_wait(1) # seconds
driver.find_elements_by_class_name("step__footer__continue-btn btn ").click()
driver.implicitly_wait(1) # seconds
driver.findElementByXpath("//div[#type='submit'][#name='button']").click();
EDIT
The key was to relocate the elements, to reload. Since I was clicking through a form, the underlying code changed.
the driver.find_element_by_xpath("//button[#type='submit'][#name='button']").click() could not find elements because of that. After reloading with driver.get ("%s/%s:%s" % (str(sys.argv[4]), str(sys.argv[2]), str(sys.argv[3]))) it worked.
Also look at the log in case some badly formatted command interrupts the flow.
You have many mistakes in your selectors, try one of those
driver.find_element_by_css_selector(".step__footer__continue-btn.btn").click() # for class with css_selector you need '.' in the beginning
driver.find_element_by_class_name("step__footer__continue-btn").click() # by_class_name gets only one class
driver.find_element_by_xpath("//button[#type='submit'][#name='button']").click() # type='submit' and name='button' are <button> tag attributes, not div
You can also try using explicit wait
WebDriverWait(driver, 10).until(expected_conditions.visibility_of_element_located((By.class_name, "step__footer__continue-btn"))).click()
Edit
Sometimes button element area is wider than the element that can receive click. You can try to click on elements in "lower" level
driver.find_element_by_class_name("btn__content").click() # <span> tag
# or
driver.find_element_by_class_name("btn__spinner").click() # <i> tag

Categories