70
from selenium import webdriver
import time

test = webdriver.Chrome()
test.get('https://docs.google.com/forms/d/e/1FAIpQLSeYUmAYYZNtbU8t8MRxwJo-        d1zkmSaEHodJXs78RzoG0yFY2w/viewform')

time.sleep(5)

Name = 'kuch bhi'
last = test.find_element_by_xpath('//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')
last.send_keys(Name)

When i execute the code, I get an error that says,

AttributeError: 'WebDriver' object has no attribute 'find_element_by_xpath'

fireslayer47
  • 803
  • 1
  • 3
  • 5

4 Answers4

146

Selenium just removed that method in version 4.3.0. See the CHANGES: https://github.com/SeleniumHQ/selenium/blob/a4995e2c096239b42c373f26498a6c9bb4f2b3e7/py/CHANGES

Selenium 4.3.0
* Deprecated find_element_by_* and find_elements_by_* are now removed (#10712)
* Deprecated Opera support has been removed (#10630)
* Fully upgraded from python 2x to 3.7 syntax and features (#10647)
* Added a devtools version fallback mechanism to look for an older version when mismatch occurs (#10749)
* Better support for co-operative multi inheritance by utilising super() throughout
* Improved type hints throughout

You now need to use:

driver.find_element("xpath", '//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')

In your example, you would use:

last = test.find_element("xpath", '//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')

For improved reliability, you should consider using WebDriverWait in combination with element_to_be_clickable.

Michael Mintz
  • 9,007
  • 6
  • 31
  • 48
  • 1
    Thanks, It worked but where did you learn to do it the new way? I have just seen the documentation, it mentions the old methods – fireslayer47 Jun 25 '22 at 16:10
  • 9
    I'm on the Selenium Technical Leadership Committee, where I spend time with the team online, and there are video calls occasionally. https://twitter.com/SeleniumBase/status/1448685115610214406?s=20&t=tx5-m9d_ea6PHpgsHEZXJA (I'm in the loop when it comes to updates.) – Michael Mintz Jun 25 '22 at 16:18
  • 1
    Oh! Please if possible in any way, just keep compatibility with older versions and/or include a depreciation warning in advance... – Peter Jul 18 '22 at 21:12
  • 2
    There was a deprecation warning before that (assuming it wasn't being ignored). And I was not in favor of this decision by the higher leadership of the Selenium committee to remove compatibility with older scripts. I created [SeleniumBase](https://github.com/seleniumbase/SeleniumBase) to do things a bit differently, and older methods don't get removed. Scripts from 2016 still work with the latest version. – Michael Mintz Jul 18 '22 at 21:46
  • How would someone go about printing all xpath IDs. for example before you could do this. ```ids = driver.find_elements_by_xpath('//*[@id]') for ii in ids: print(ii.get_attribute('id'))``` – Swannie Oct 05 '22 at 14:50
  • 1
    @Swannie For finding multiple elements and making a list: ``driver.find_elements(by=by, value=selector)`` – Michael Mintz Oct 05 '22 at 15:19
  • 145 k views - not such a bad outcome for an IMHO awfully bad decision – Wolfgang Fahl Jul 31 '23 at 16:49
24

You can now use:

from selenium.webdriver.common.by import By

driver.find_element(by=By.XPATH, value='//<your xpath>')
Uri
  • 2,992
  • 8
  • 43
  • 86
15

As per the changelogs of Selenium 4.3.0:

Selenium 4.3.0
* Deprecated find_element_by_* and find_elements_by_* are now removed (#10712)

and as per the merge the 16 replaced strings are as follows:

.find_element_by_class_name(
.find_element(By.CLASS_NAME, 

.find_element_by_css_selector(
.find_element(By.CSS_SELECTOR, 

.find_element_by_id(
.find_element(By.ID, 

.find_element_by_link_text(
.find_element(By.LINK_TEXT, 

.find_element_by_name(
.find_element(By.NAME, 

.find_element_by_partial_link_text(
.find_element(By.PARTIAL_LINK_TEXT, 

.find_element_by_tag_name(
.find_element(By.TAG_NAME, 

.find_element_by_xpath(
.find_element(By.XPATH, 

.find_elements_by_class_name(
.find_elements(By.CLASS_NAME, 

.find_elements_by_css_selector(
.find_elements(By.CSS_SELECTOR, 

.find_elements_by_id(
.find_elements(By.ID, 

.find_elements_by_link_text(
.find_elements(By.LINK_TEXT, 

.find_elements_by_name(
.find_elements(By.NAME, 

.find_elements_by_partial_link_text(
.find_elements(By.PARTIAL_LINK_TEXT, 

.find_elements_by_tag_name(
.find_elements(By.TAG_NAME, 

.find_elements_by_xpath(
.find_elements(By.XPATH,

This usecase

So effectively you have to replace the line of code:

last = test.find_element_by_xpath('//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')

as:

last = test.find_element(By.XPATH, '//*[@id="mG61Hd"]/div[2]/div/div[2]/div[1]/div/div/div[2]/div/div[1]/div/div[1]/input')

Note

You will also need to import By as follows:

from selenium.webdriver.common.by import By
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
0

e = driver.find_element(by.By.XPATH,'//label[@analytics-event="All matches"]') from selenium.webdriver.common import by