Looping on elements of a class python selenium - python

I've a code for sending request to people on instagram. It scrollings following box and send requests. But sometimes it cannot find element and it gives error. I want to turn my code more general.
I takes 12 element each scrolling. How can i say that find the request button on each element?
elements = self.driver.find_elements(By.XPATH, '//div[#class="_aano"]//a/span/div')[-12:]
for element in elements:
button = element.find_element(By.XPATH,'//div[#class="_ab8w _ab94 _ab97 _ab9h _ab9k _ab9p _abb0 _abcm"])
but it doesn't work because it cannot find button.
To illustrates, _aano class which includes follower and the second class that i want to click.
Can you please help me?

Related

locate html element that change position with selenium Python

List:
So i have this list and need a way to find any of the users, the problem is that the position of users changes and with xpath is imposible because the div position takes the users thats in that div, not the user that a want to find
//*[#id="main-el"]/div[3]/div/div[2] #the last div number is the location of user
and on top of that the users element doesnt have any unique identification other than the xpath or css colector
so, any help?
im putting here the hmtl element too if someone needs it, is there other way to find the element?
Html Code of element:
Never mind i got it
i just had to find an unique property of the div, in my case was
"data-rbd-draggable-id" of the user div, so i put this Xpath
//div[#data-rbd-draggable-id="US_true_af26b3c3-4216-43e0-ba73-9ad890058060"]
and it worked, it detects the user prueba1 element even if it changes position
from selenium.webdriver import ActionChains
actions = ActionChains(self.driver)
el = self.driver.find_element_by_xpath("locator")
actions.move_to_element(el).perform()

Selecting a button, list object has no attribute click python selenium

After searching for a while an answer to my question, I couldn't get an answer that helped me, so here I am asking for your help ! :)
Right now, I am trying to select a plan on a website page which, after it has been selected (Read : a certain button clicked) displays the rest of the page where I can send the keys / values that I want to send.
Here is the code I am using
select_plan = browser.find_elements_by_xpath(".//*[#id='PostAdMainForm']/div[1]/div/div/div/div/div[1]/div[3]/button")
select_plan.click()
I found the xpath with Firepath, but when I run my code it gives me a AttributeError: 'list' object has no attribute 'click'
Here is the page I am trying to click from
https://www.kijiji.ca/p-post-ad.html?categoryId=214&hpGalleryAddOn=false&postAs=ownr
(I am looking to click on the left button, the one in blue)
Thank you very much for you help :)
The method find_elements returns a list, not a single element. You are taking the result and trying to click on it. Like the error says, you can't click on a list.
Either use find_element (singular) or use find_elements (plural) and then click on one of the elements that was returned.
# using find_elements
select_plans = browser.find_elements_by_xpath(".//*[#id='PostAdMainForm']/div[1]/div/div/div/div/div[1]/div[3]/button")
if len(select_plans) > 0:
select_plans[0].click()
# using find_element
select_plan = browser.find_element_by_xpath(".//*[#id='PostAdMainForm']/div[1]/div/div/div/div/div[1]/div[3]/button")
if select_plan:
select_plan.click()
Though, the link for the page you shared did not have the blue button. However, I have found it, after navigating to 'Post Your Ad' page. You can click on the Select button which is in blue color using the text appearing before it. For example, using text Basic, you can reach to the Select button. Following code shows, how we can achieve this:
select_plan = browser.find_element_by_xpath("//h3[text()='Basic']/following::button[text()='Select'][1]")
select_plan.click()
Let me know, whether it works for you.

Using Selenium in Python to click through all elements with the same class name

I am trying to click on all of the "like" buttons on a webpage. I know how to click on one of them, but I'd like to be able to click them all. They have the same class name, but different id's.
Do I need to create some sort of list and tell it to click on each one of the items on the list? Is there a way to write "click all"?
Here's what my code looks like (I removed the login code):
from selenium import webdriver
from selenium.webdriver.common.keys import Keys
browser = webdriver.Firefox()
browser.set_window_size(650, 700)
browser.get('http://iconosquare.com/viewer.php#/tag/searchterm/grid')
mobile = browser.find_element_by_id('open-menu-mobile')
mobile.click()
search = browser.find_element_by_id('getSearch')
search.click()
search.send_keys('input search term' + Keys.RETURN)
#this gets me to the page I want to click the likes
fitness = browser.find_element_by_css_selector("a[href*='fitness/']")
fitness.click()
#here are the different codes I've tried to use to click all of the "like buttons"
#tried to create a list of all elements with "like" in the id and click on all of them. It didn't work.
like = browser.find_elements_by_id('like')
for x in range(0,len(like)):
if like[x].is_displayed():
like[x].click()
#tried to create a list by class and click on everything within the list and it didn't work.
like = browser.find_elements_by_class_name('like_picto_unselected')
like.click()
AttributeError: 'list' object has no attribute 'click'
I know I can't click on a list because it isn't a single object, but I have no idea how I'd go about this otherwise.
Your help is greatly appreciated.
This is unfortunate, you got two halves of the whole, you cannot find multiple elements by id as ID is unique to a single element.
so combine the iterative method you use with id and the find by elements with classes to get:
like = browser.find_elements_by_class_name('like_picto_unselected')
for x in range(0,len(like)):
if like[x].is_displayed():
like[x].click()
I strongly suspect this will work for you. Please tell me if not.

How to send keys to a difficult element in selenium (Python)

I am trying to click a small button, which has no "ID" or "Name", on a website. The only unique identifier is onclick, which is as follows:
onclick="submitForm('DefaultFormName',1,{'param1':'HXCTIMECARDACTIVITIESPAGEXgm7J5oT','serverValidate':'1uCdqvhJe','param2':'',event:'details|1'});return false;"
However, another button on the page has the following onclick:
onclick="submitForm('DefaultFormName',1,{'param1':'HXCTIMECARDACTIVITIESPAGEXgm7J5oT','serverValidate':'1uCdqvhJe','param2':'',event:'details|2'});return false;"
The only difference is a 1 vs. a 2 in the middle of the code. I tried to use a "find_element_by_css_selector" with the following code but it didn't work:
driver.find_element_by_css_selector(".x1p[onclick*='details|1']").click()
Another option would be selecting the preceding element, with the following code:
precedingbutton = driver.find_element_by_name('B22_1_6')
And then sending tab and then enter. However, after I send Tab, I don't know of a way to send Enter without assigning the Send_Keys command back to the preceding box, which deselects the button I want.
Let me know if you can help!
If you can locate the parent, you can locate the child, either with xpath or the nth-child css selector, relative to it.
Edit in response to comments:
Assuming by "2 elements away" you mean it is a sibling preceding the target, try something like td[name="B22_1_6"] + td + td. This is the sibling selector.
You can do it easily by
driver.find_element(By.XPATH, 'your xpath').click()
For finding the xpath , just inspect the button with firebug, and in html tab right click on selected element and click on Copy XPath.
Hope it will help you.

Unable to type into text field of Javascript form with Selenium / Python (element not interactable)

I'm using Selenium and coding with Python.
I'm trying to do the following: for a flight search website, under Flight 1's 'Enter routing code' text box, type 'AA'
This is the code that I have at the moment:
flight1_routing = driver.find_element_by_xpath(".//*[#id='ita_form_location_RouteLanguageTextBox_0']")
flight1_routing.clear()
flight1_origin.send_keys("AA")
But instead, I get this error message: "invalid element state: Element is not currently interactable and may not be manipulated". How can this be with a regular text field that is also not an autocomplete field, AFAIK?
if you get Element is not currently interactable check if the element is not disabled and its visible. if you want to hack it execute JS to enable it.
i visited the homepage id ita_form_location_RouteLanguageTextBox_0 doesnt exist also under flight one there's no Enter routing code. i can see the text box saying airport city or city name
Also if you have the id prefer to use find_element_by_id if not try to use css selector if you can rather than xpath. Its much cleaner.
Update
here's a working script:
As recomended above, the elements selected are not visible. what is actualy done, is that there's 5-6 different elements all hidden and when you click on show advanced route it picks 2 random ones and makes them visible.
So the id is not always the same. If you use the same id you will get a hidden element some times(because it picks random ids) so selenium is not able to deal with it. i made a selector that gets the 2 hidden elements
from selenium import webdriver
import selenium.webdriver.support.ui as ui
driver = webdriver.Firefox()
driver.get("http://matrix.itasoftware.com/")
#click on the multi tab
tab = driver.find_element_by_id("ita_layout_TabContainer_0_tablist_ita_form_multislice_MultiSliceForm_0").click()
#click on the advanced routes
advanced_routing=ui.WebDriverWait(driver, 10).until(
lambda driver : driver.find_element_by_id("sites_matrix_layout_RouteLanguageToggleLink_1")
)
advanced_routing.click()
#get all visible elements with id like ita_form_location_RouteLanguageTextBox. its similar to regex ita_form_location_RouteLanguageTextBox.*
element = ui.WebDriverWait(driver, 10).until(
lambda driver : driver.find_elements_by_css_selector("[id*=ita_form_multislice_MultiSliceRow] [id*=ita_form_location_RouteLanguageTextBox]")
)
element[0].send_keys("foo")
element[1].send_keys("bar")
import time
time.sleep(20)
Did you click into the correct tab first & enable advanced routing codes?? e.g.
#Go to right tab
driver.find_element_by_css_selector("div#ta_layout_TabContainer_0_tablist_ita_form_multislice_MultiSliceForm_0 > span").click()
#Enable routing
driver.find_element_by_css_selector("a.itaToggleLink").click()
#note I seem to get a different id to the one you're using, assuming its dynamic numbering so handling all cases
#if you know how the dynamic numbering works youmay be able to deduce a single id that will work for your test case
#Instead I'm going for finding all elements matching a pattern then searching through them, assuming only one will be visible
flight1_routings = driver.find_elements_by_css_selector("input[id^='ita_form_location_RouteLanguageTextBox_']")
#probably better finding it then using it separately, but I was feeling lazy sorry.
for route in flight1_routings:
if route.is_displayed():
route.clear()
route.send_keys("AA")
Also you can probably skip the .clear() call as it looks like the box starts with no text to overwrite.
Edit: Updated the enable routing toggling to handle not knowing the id, the class name stays the same, should work. Handling finding the input despite variable id as suggested by foo bar with the css selector, just then iterating over that list and checking if its on top

Categories

Resources