How to split list of coordinates into separate variables?
Question:
I’m trying to split coordinates of elements that I find like this
elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))
When I only have to find coordinates of element that appears only once I just use .location, but my problem is when I have to find element that appears more then once. I tried doing it like this but it doesn’t work
elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))
elementlist = []
for element in elements:
elementlocation = element.location
elementlist.append(location)
print(elementlist)
x,y = elementlist.split(",")
print(x,y)
I tried getting list of coordinates of element that appears multiple times, split them into separate variables x,y and print them out
Update :
<div class="gl-MarketGroup_Wrapper ">
<div class="srb-Market25Wrapping gl-Market_General gl-Market_General-columnheader gl-Market_General-haslabels gl-Market_General-pwidth12-5 ">
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">100</div>
</div>
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">110</div>
</div>
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">120</div>
</div>
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">130</div>
</div>
</div>
<div class="srb-Market375Wrapping gl-Market_General gl-Market_General-columnheader gl-Market_General-pwidth18-75 ">
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">2</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">3</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
</div>
<div class="srb-Market375Wrapping gl-Market_General gl-Market_General-columnheader gl-Market_General-pwidth18-75 ">
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">2</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">2</span>
</div>
</div>
</div>
I want to find element that contains text "1" that is on same height like element that contains text "110"
Answers:
You didn’t say what are your elements, but considering they are instances of some class which has location
property:
element_locations = [x,y for x,y in element.location.split(",") for element in elements]
# This is gonna be a list [(x1,y1), (x2,y2), ...,(xn,yn)]
location
The location
attribute contains the location of the WebElement in the renderable canvas in the form of a dict
.
Solution
To print the x,y
location of the elements you can use:
print([element.location for element in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))])
# outputs -> [{'x': 100, 'y': 367}, {'x': 100, 'y': 684}, {'x': 100, 'y': 684}, {'x': 100, 'y': 684}, {'x': 100, 'y': 1917}]
To print only the coordinates:
print([(element.location['x'],element.location['y']) for element in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))])
# outputs -> [(100, 367), (100, 684), (100, 684), (100, 684), (100, 1917)]
You can find a relevant detailed discussion in Selenium: get coordinates or dimensions of element with Python
As we discussed, there’s a better way to approach this problem than using locations and comparing Y values. Using XPaths you can get the desired element from the first column and then get the other elements in that same row. This HTML was more difficult because instead of an HTML TABLE, it only looked like a table but was instead a grid formed by DIVs. Anyway…
-
Get the desired element from column 1
We can simply use an XPath
col1_value = "120"
//div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']
-
Get the row number that contains the desired element
Once we have the desired element from Step 1, we need to get it’s row #. To do this, we create an XPath
count(//div[./div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']]/preceding-sibling::div)
Basically we’re getting the element from step 1, going up on level in the DOM, and then counting the preceding DIVs. Once we have that, we add 1 to get the row #
-
Get the element in the same row from column 2
Here we just use the row # from the step above as an index into column 2 and return the desired element from that column using the expected text, colX_value
colX_value = "1"
//div[" + row + "]/span[@class='gl-ParticipantOddsOnly_Odds'][text()='" + colX_value + "']
Putting this all together in actual code
col1_value = "120"
colX_value = "1"
row = driver.execute_script("document.evaluate("count(//div[./div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']]/preceding-sibling::div)", document, null, XPathResult.NUMBER_TYPE, null).numberValue") + 1
col2_value = driver.find_element(By.XPATH, "//div[" + row + "]/span[@class='gl-ParticipantOddsOnly_Odds'][text()='" + colX_value + "']").text
I’m trying to split coordinates of elements that I find like this
elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))
When I only have to find coordinates of element that appears only once I just use .location, but my problem is when I have to find element that appears more then once. I tried doing it like this but it doesn’t work
elements = WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))
elementlist = []
for element in elements:
elementlocation = element.location
elementlist.append(location)
print(elementlist)
x,y = elementlist.split(",")
print(x,y)
I tried getting list of coordinates of element that appears multiple times, split them into separate variables x,y and print them out
Update :
<div class="gl-MarketGroup_Wrapper ">
<div class="srb-Market25Wrapping gl-Market_General gl-Market_General-columnheader gl-Market_General-haslabels gl-Market_General-pwidth12-5 ">
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">100</div>
</div>
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">110</div>
</div>
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">120</div>
</div>
<div class="srb-ParticipantLabelCentered gl-Market_General-cn1 ">
<div class="srb-ParticipantLabelCentered_Name ">130</div>
</div>
</div>
<div class="srb-Market375Wrapping gl-Market_General gl-Market_General-columnheader gl-Market_General-pwidth18-75 ">
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">2</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">3</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
</div>
<div class="srb-Market375Wrapping gl-Market_General gl-Market_General-columnheader gl-Market_General-pwidth18-75 ">
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">2</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">1</span>
</div>
<div class="gl-ParticipantOddsOnly gl-Participant_General gl-Market_General-cn1 ">
<span class="gl-ParticipantOddsOnly_Odds">2</span>
</div>
</div>
</div>
I want to find element that contains text "1" that is on same height like element that contains text "110"
You didn’t say what are your elements, but considering they are instances of some class which has location
property:
element_locations = [x,y for x,y in element.location.split(",") for element in elements]
# This is gonna be a list [(x1,y1), (x2,y2), ...,(xn,yn)]
location
The location
attribute contains the location of the WebElement in the renderable canvas in the form of a dict
.
Solution
To print the x,y
location of the elements you can use:
print([element.location for element in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))])
# outputs -> [{'x': 100, 'y': 367}, {'x': 100, 'y': 684}, {'x': 100, 'y': 684}, {'x': 100, 'y': 684}, {'x': 100, 'y': 1917}]
To print only the coordinates:
print([(element.location['x'],element.location['y']) for element in WebDriverWait(driver, 20).until(EC.visibility_of_all_elements_located((By.XPATH, "//span[text() ='100']")))])
# outputs -> [(100, 367), (100, 684), (100, 684), (100, 684), (100, 1917)]
You can find a relevant detailed discussion in Selenium: get coordinates or dimensions of element with Python
As we discussed, there’s a better way to approach this problem than using locations and comparing Y values. Using XPaths you can get the desired element from the first column and then get the other elements in that same row. This HTML was more difficult because instead of an HTML TABLE, it only looked like a table but was instead a grid formed by DIVs. Anyway…
-
Get the desired element from column 1
We can simply use an XPath
col1_value = "120" //div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']
-
Get the row number that contains the desired element
Once we have the desired element from Step 1, we need to get it’s row #. To do this, we create an XPath
count(//div[./div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']]/preceding-sibling::div)
Basically we’re getting the element from step 1, going up on level in the DOM, and then counting the preceding DIVs. Once we have that, we add 1 to get the row #
-
Get the element in the same row from column 2
Here we just use the row # from the step above as an index into column 2 and return the desired element from that column using the expected text,
colX_value
colX_value = "1" //div[" + row + "]/span[@class='gl-ParticipantOddsOnly_Odds'][text()='" + colX_value + "']
Putting this all together in actual code
col1_value = "120"
colX_value = "1"
row = driver.execute_script("document.evaluate("count(//div[./div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']]/preceding-sibling::div)", document, null, XPathResult.NUMBER_TYPE, null).numberValue") + 1
col2_value = driver.find_element(By.XPATH, "//div[" + row + "]/span[@class='gl-ParticipantOddsOnly_Odds'][text()='" + colX_value + "']").text