Last active
July 5, 2023 02:35
-
-
Save stachjankowski/455672437b0f1285514f2f7200d28a49 to your computer and use it in GitHub Desktop.
Get the xpath of an element. This is useful for creating selectors for selenium.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from typing import List | |
from selenium.common import InvalidSelectorException | |
from selenium.webdriver.common.by import By | |
from selenium.webdriver.remote.webelement import WebElement | |
def get_xpath_for_selenium_element(element: WebElement, use_index: bool = True, | |
attributes: List[str] = ['id']) -> str: | |
"""Get the xpath of an element. This is useful for creating selectors for selenium. | |
:param element: The element to get the xpath of. | |
:param use_index: Whether to use the index of the element in the xpath. | |
:param attributes: The attributes to use in the xpath. | |
:return: The xpath of the element. | |
""" | |
xpath_parts: List[str] = [] | |
while element: | |
# Get the attributes selector of the element | |
attributes_selector = get_attributes_selector(element, attributes) | |
tag_name = element.tag_name | |
if attributes_selector: | |
# If there are attribute parts, add them to the xpath | |
xpath_parts.insert(0, f"{tag_name}{attributes_selector}") | |
elif use_index: | |
# Find all sibling elements with the same tag name | |
previous_elements = element.find_elements(By.XPATH, f"preceding-sibling::{tag_name}") | |
next_elements = element.find_elements(By.XPATH, f"following-sibling::{tag_name}") | |
index = len(previous_elements) + 1 | |
if previous_elements or next_elements: | |
xpath_parts.insert(0, f"{tag_name}[{index}]") | |
else: | |
xpath_parts.insert(0, f"{tag_name}") | |
else: | |
xpath_parts.insert(0, f"{tag_name}") | |
# Try to find the parent element | |
try: | |
element = element.find_element(By.XPATH, "..") | |
except InvalidSelectorException: | |
break | |
return "/" + "/".join(xpath_parts) | |
def get_attributes_selector(element: WebElement, attributes: List[str]) -> str: | |
"""Get the attributes selector of an element. | |
:param element: The element to get the attributes selector of. | |
:param attributes: The attributes to use in the selector. | |
:return: The attributes selector of the element. | |
""" | |
attributes_parts = [ | |
f"[@{attribute}='{escaped_value}']" | |
for attribute in attributes | |
if (value := element.get_attribute(attribute)) and (escaped_value := value.replace("'", "\\'")) | |
] | |
return "".join(attributes_parts) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Example usage: