1

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

JeffC
  • 22,180
  • 5
  • 32
  • 55
ElBob
  • 51
  • 5
  • "it doesn't work" you got an error? I think you should replace `elementlist.append(location)` with `elementlist.append(elementlocation)` – sound wave Feb 03 '23 at 14:54
  • You see `elementlist` is a type of `list` and `list` objects do not have an attribute named `split`. What you need to do is to split each element of the list. – MSH Feb 03 '23 at 14:56
  • Why are you trying to get the x,y values of each element? What do you plan to do with that? Even an element that appears multiple times would have a different location... why split them into x,y pairs? – JeffC Feb 03 '23 at 16:33
  • @JeffC I want to compare their x,y coordinates with other element and depending if y coordinate of one of elements in list matches to do something and if not do something else – ElBob Feb 03 '23 at 16:37
  • Are you trying to process elements in a table row or ? I'm just trying to understand your scenario to see if there is a simpler approach. – JeffC Feb 03 '23 at 16:57
  • @JeffC Yes the elements are in one large table and I'm trying to compare y coordinate of element that is always in column 1 with elements that are placed at random locations in columns 2,3,4......, but also they could be placed outside of the table. All columns have only 1 row and all columns are located inside of container. – ElBob Feb 03 '23 at 17:04
  • OK, great. There's a much simpler way to do this without having to rely on locations or coordinates. We can use an XPath locator to find the desired element, get that table row, and then find other elements in that table row. Can you please update your question with some sample rows from the HTML table and then describe which elements you are looking for? – JeffC Feb 03 '23 at 17:08
  • @JeffC I added html and tried to explain what I want to accomplish – ElBob Feb 03 '23 at 17:33
  • @ElBob Please don't change the question based on which you have received well researched answers. Once you receive canonical answers changing the question can make all the existing answers invalid and may not be useful to future readers. If your requirement have changed feel free to raise a new question. StackOverflow contributors will be happy to help you out. For the time being I have reverted back the question to it's initial state. – undetected Selenium Feb 04 '23 at 11:27
  • The question wasn't changed, it was clarified. It was an XY problem that he and I got to the root of. We should all spend more time helping question askers clarify and focus problems rather than rushing to answer questions. The location path is a more difficult path vs just using locators to find the other desired elements in the same row. – JeffC Feb 05 '23 at 02:59

3 Answers3

1

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)] 
Gameplay
  • 1,142
  • 1
  • 4
  • 16
1

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

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • Thank you it's working, but I still can't figure out how to turn x and y coordinates into separate variables so I can use them from list. So I can use them like if x of first element in list is equal to. I tried replacing print with list = and then x1, y1 = list, but now I get both x and y coordinates for first element, except just the x value – ElBob Feb 03 '23 at 16:50
  • @ElBob The x and y values are in the form of a [_**dictionary**_](https://www.w3schools.com/python/python_dictionaries.asp). See the [**Dictionary Methods**](https://www.freecodecamp.org/news/python-dictionary-methods-dictionaries-in-python/) – undetected Selenium Feb 03 '23 at 17:13
1

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
JeffC
  • 22,180
  • 5
  • 32
  • 55
  • Thank you, it's working but what if element is not in column 2, but in some other column that is not 1 or 2, like 3,4,5,6....? I know what text that element contains, but it can be in any column except column 1 so based on that text is there a way like you did but so it finds element that contains specific text that is in same row as element in column 1. Example : col1_value = "120" and it needs to find element that contains text "1" , but I don't know in which column it is, only that it's on same row as col1_value = "120" – ElBob Feb 03 '23 at 18:58
  • I updated my answer, did you ever get a chance to see if it worked for you? – JeffC Feb 05 '23 at 03:02
  • Yes, I tried it , it's working, I only made a tweak so I can use decimal numbers, with "120" was working fine, but when I used something like "120.74" I was getting an error, but now it's working all fine. Thank you for your help. – ElBob Feb 05 '23 at 17:12