Rishi
Rishi

Reputation: 97

Cannot access element via Selenium via xpath

I am trying to use selenium to extract a list of cases from the top bar (confirmed, active, recovered, deceased) of this Covid website for both daily and cumulative. Trying to do so via a list for the top-level class (= 'Level') and then use XPATH for h1 and h4 tags. But I keep getting an 'unable to locate element' error. What am I doing wrong? I've also tried using a wait time but doesn't seem to help.

from selenium import webdriver
from time import sleep
from selenium.webdriver.support import expected_conditions as EC

PATH = 'ChromeDriver/chromedriver'

driver = webdriver.Chrome(PATH)
driver.get('https://www.covid19india.org/')

sleep(5)

confirmed = driver.find_elements_by_class_name('Level')
for item in confirmed:
    daily = item.find_element_by_xpath('.//*[@id="root"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/h4').text
    cumulative = item.find_element_by_xpath('.//*[@id="root"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/h1').text
    print(daily, cumulative)
print(confirmed)

And here's the traceback:

Traceback (most recent call last):
  File "/Users/rssaiki/Programming/Youtube/covid_selenium.py", line 14, in <module>
    daily = item.find_element_by_xpath('.//*[@id="root"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/h4').text
  File "/Users/rssaiki/Programming/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webelement.py", line 351, in find_element_by_xpath
    return self.find_element(by=By.XPATH, value=xpath)
  File "/Users/rssaiki/Programming/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webelement.py", line 658, in find_element
    return self._execute(Command.FIND_CHILD_ELEMENT,
  File "/Users/rssaiki/Programming/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webelement.py", line 633, in _execute
    return self._parent.execute(command, params)
  File "/Users/rssaiki/Programming/venv/lib/python3.9/site-packages/selenium/webdriver/remote/webdriver.py", line 321, in execute
    self.error_handler.check_response(response)
  File "/Users/rssaiki/Programming/venv/lib/python3.9/site-packages/selenium/webdriver/remote/errorhandler.py", line 242, in check_response
    raise exception_class(message, screen, stacktrace)
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"xpath","selector":".//*[@id="root"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/h4"}
  (Session info: chrome=90.0.4430.93)

Upvotes: 1

Views: 660

Answers (3)

Moshe Slavin
Moshe Slavin

Reputation: 5214

As The @Prophet said Level has only one element.

You should not use the absolute path for your Xpath's, use WebDriverWait instead of sleep.

Here is a snip you can find helpful:

WebDriverWait(driver, 30).until(EC.presence_of_all_elements_located((By.XPATH,"//div[contains(@class, 'level-item')]")))
a = driver.find_elements_by_xpath("//div[contains(@class, 'level-item')]//h5")
b = driver.find_elements_by_xpath("//div[contains(@class, 'level-item')]//h4")
c = driver.find_elements_by_xpath("//div[contains(@class, 'level-item')]//h1")

for i in range(len(a)):
    print(a[i].get_attribute("innerText"))
    print(b[i].get_attribute("innerText"))
    print(c[i].get_attribute("innerText"))

Confirmed + 25,136 2,23,21,229

Active   37,42,119

Recovered + 15,165 1,83,26,851

Deceased + 313 2,42,712

You will need to rearrange the code!

Upvotes: 1

Bhavya Parikh
Bhavya Parikh

Reputation: 3400

NO need of . requires in xpath due to that it can't find the location of element

from selenium import webdriver
from time import sleep
from selenium.webdriver.support import expected_conditions as EC

PATH = 'C:\Program Files (x86)\chromedriver.exe'

driver = webdriver.Chrome(PATH)
driver.get('https://www.covid19india.org/')

sleep(5)

daily=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[1]/div[2]/div[2]/div[1]/h4').text
confirmed=driver.find_element_by_xpath('//*[@id="root"]/div/div[2]/div[1]/div[2]/div[2]/div[1]/h1').text
print(daily)
print(confirmed)

Output:
+ 11,155
2,23,07,248

Upvotes: 1

Prophet
Prophet

Reputation: 33351

  1. There is only 1 element located by class name Level so you should use find_element_by_class_name instead of find_elements_by_class_name to locate it.
  2. Since it's only 1 element there, you should not try iterating on the confirmed list.
  3. I see no elements located by .//*[@id="root"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/h4 or by .//*[@id="root"]/div/div[2]/div[1]/div[2]/div[1]/div[1]/h1 below the element located by Level class name there

Upvotes: 1

Related Questions