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"

Like in this image enter image description here

Asked By: ElBob

||

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)] 
Answered By: Gameplay

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

Answered By: undetected Selenium

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…

  1. Get the desired element from column 1

    We can simply use an XPath

    col1_value = "120"
    //div[@class='srb-ParticipantLabelCentered_Name '][text()='" + col1_value + "']
    
  2. 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 #

  3. 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
Answered By: JeffC