2

Working on removing boring stuff from my job. Below you find the Python's Selenium library being used to access the website containing German companies' registers. It does the following:

  1. opens the Handelsregister website,
  2. looks for the "normal search" button and presses it,
  3. looks for the field where company's name has to be input,
  4. input chosen company's name,
  5. changes the search manner to "contain the exact name of the company" and presses the "find" button,
  6. presses the "CD" button (CD is a type of register).

Then the site requires you to login in order to download the register, so the last thing you should see is the login page. I show you the error first, if I do it at the bottom it shows up as part of the code.

Traceback (most recent call last): File "C:/Users/adria/.PyCharmCE2019.1/config/scratches/Handelsregister_login_downloadCD.py", line 28, in choose_class_CD_0 = chrome.find_element(by=By.CLASS_NAME, value='RegPortErg') File "C:\Users\adria\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 978, in find_element 'value': value})['value'] File "C:\Users\adria\Anaconda3\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 321, in execute self.error_handler.check_response(response) File "C:\Users\adria\Anaconda3\lib\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":"css selector","selector":".RegPortErg"} (Session info: chrome=78.0.3904.108)

Now, how is it possible that the following code works, while it doesn't once I remove the #-commented strings, giving away the above error?

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

chrome = webdriver.Chrome(executable_path=r"C:\Users\...\Desktop\chromedriver_win32\chromedriver.exe")
chrome.get('https://www.handelsregister.de/')
assert "Register" in chrome.title

normal_search = chrome.find_element(by=By.ID, value='main.search')
normal_search.send_keys(Keys.ENTER)
# input_company_name_0 = chrome.find_element_by_id('container')
# input_company_name_1 = chrome.find_element_by_id('inhalt')
# input_company_name_2 = chrome.find_element_by_id('suchparameterForm')
input_company_name = chrome.find_element_by_name('schlagwoerter')
input_company_name.clear()
input_company_name.send_keys('Sparkasse Dortmund')
keywords = chrome.find_element_by_id('schlagwortOption3')
keywords.send_keys(Keys.SPACE)
find_button = chrome.find_element_by_id('submitBtn')
find_button.send_keys(Keys.ENTER)
choose_class_CD_0 = chrome.find_element(by=By.CLASS_NAME, value='RegPortErg')
# choose_class_CD_1 = chrome.find_element(by=By.CLASS_NAME, value='RegPortErg_RandRechts')
choose_CD = chrome.find_element(by=By.LINK_TEXT, value="CD")
choose_CD.send_keys(Keys.ENTER)
undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
adry_seme
  • 23
  • 3
  • 2
    if it works with all of those lines uncommented, can you comment each one individually to try to narrow down which one specifically is breaking it? that might help you pinpoint the problem solution. if you add a timeout to the find_element calls to give the page time to load, does that do anything? – swaggy p Dec 03 '19 at 22:37
  • 1
    Tried this once, as far as I remember it then randomly worked or not worked. I have suspicion that Christine and Debanjan who posted below are right when saying the browser has no time to load its structure, while the code is hurrying in doing all the steps. Hope to find time this evening in order to test their solutions. – adry_seme Dec 05 '19 at 07:16

2 Answers2

1

It seems a bit weird to me that comments would affect your code, unless there's some inherent issue with the parser you are using to run Python.

You are receiving a NoSuchElementException -- it may be possible that the element you are looking for on the page has not fully loaded before you attempt to locate it. This would result in the exception you are seeing.

To fix this, I would add some WebDriverWait into your code to wait on elements before you attempt to locate them.

Here's how I would refactor your code:

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys


chrome = webdriver.Chrome()
chrome.get('https://www.handelsregister.de/')

assert "Register" in chrome.title

# wait on & locate 'normal search'
normal_search = WebDriverWait(chrome, 10).until(EC.presence_of_element_located((By.ID, "main.search")))
normal_search.send_keys(Keys.ENTER)

# wait on & input 'company name'
input_company_name = WebDriverWait(chrome, 10).until(EC.presence_of_element_located((By.NAME, "schlagwoerter")))
input_company_name.clear()
input_company_name.send_keys('Sparkasse Dortmund')

# select the radio button
chrome.find_element_by_id('schlagwortOption3').click()

# find and click submit button
chrome.find_element_by_id('submitBtn').click()

# wait for this element to exist before locating it
choose_class_CD_0 = WebDriverWait(chrome, 10).until(EC.presence_of_element_located((By.CLASS_NAME, "RegPortErg")))
choose_CD = chrome.find_element(by=By.LINK_TEXT, value="CD")
choose_CD.send_keys(Keys.ENTER)

chrome.close()
chrome.quit()

The issue I noticed when running your code was that form on 'Normal Search' page was never getting submitted, and we were not getting taken to the next page at all. I noticed the "Company or Keywords" field was not actually receiving any text input, and the radio button for "contain the exact name of the company" was also not getting ticked.

I fixed these issues by adding a WebDriverWait on the "Company or Keywords" field, because that's the first element on the page that we interact with. The send_keys operation was probably happening before the element was fully loaded, resulting in blank key send.

I also noticed you were using KEYS.Space and KEYS.Enter to simulate clicking elements -- while this may work for this website, there's nothing wrong with using a plain Selenium .click() for scenarios like this. I updated that in your code as well.

I left comments throughout the code to keep track of what I changed and I hope you find them helpful. I successfully ran the above code sample provided and did not receive the NoSuchElementException. The "Normal Search" form was successfully submitted, and took me to the next page, where the RegPortErg was successfully located.

Hopefully this WebDriverWait will help you continue this script without issue.

CEH
  • 5,701
  • 2
  • 16
  • 40
  • Lots of useful insight. :) As for now Christine, I can thank you for all, from your time to the having given away a ready-to-paste code. I promise I'll type it all in order to understand each step, hope to return with a positive feedback this evening! – adry_seme Dec 05 '19 at 07:03
  • @adry_seme Glad you found this useful. Any feedback relating to your findings will be helpful for me. – CEH Dec 05 '19 at 16:52
  • Working on your code, getting TimeoutException on the same line I got the error mentioned in my post. Traceback (most recent call last): File "C:/Users/adria/.PyCharmCE2019.1/config/scratches/Handelsregister_login_downloadCD.py", line 31, in choose_class_CD = WebDriverWait(chrome, 10).until(EC.presence_of_element_located((By.CLASS_NAME, 'RegPortErg'))) File "C:\Users\adria\Anaconda3\lib\site-packages\selenium\webdriver\support\wait.py", line 80, in until raise TimeoutException(message, screen, stacktrace) selenium.common.exceptions.TimeoutException: Message: – adry_seme Dec 05 '19 at 20:07
  • Moreover, I began adding the login procedure to the code, prior searching for the register. There are times when the script don't even consider the part looking for the login page, however it worked flawless at the very beginning, when the script had only code which would log into the platform without the register search. I'll edit my original post to include this. – adry_seme Dec 05 '19 at 20:10
  • Oki I think now everything works, likely placing the login procedure at the end was a bad one. If I force to log in and then search the company all works fine. Thanks a lot Christine! – adry_seme Dec 05 '19 at 20:28
  • Glad to see you got the issues worked out, hopefully methods such as `WebDriverWait` can prove useful in your future automation. – CEH Dec 05 '19 at 22:57
1

To open the site https://www.handelsregister.de/ and perform the mentioned steps to reach to the Login Page you need to induce WebDriverWait for the element_to_be_clickable() and you can use the following Locator Strategies:

  • Code Block:

    from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
    from selenium.webdriver.support import expected_conditions as EC
    
    options = webdriver.ChromeOptions() 
    options.add_argument("start-maximized")
    options.add_experimental_option("excludeSwitches", ["enable-automation"])
    options.add_experimental_option('useAutomationExtension', False)
    driver = webdriver.Chrome(options=options, executable_path=r'C:\Utility\BrowserDrivers\chromedriver.exe')
    driver.get("https://www.handelsregister.de/rp_web/welcome.do")
    WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "//ul[@class='hinterlegt']/li/a[text()='Normal search']"))).click()
    WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "//textarea[@name='schlagwoerter']"))).send_keys("Sparkasse Dortmund")
    driver.find_element_by_xpath("//label[@for='schlagwortOption3']").click()
    driver.find_element_by_xpath("//input[@id='submitBtn']").click()
    WebDriverWait(driver, 5).until(EC.element_to_be_clickable((By.XPATH, "//td[@class='RegPortErg_RandRechts']//a[text()='CD']"))).click()
    
  • Browser Snapshot:

handelsregister

undetected Selenium
  • 183,867
  • 41
  • 278
  • 352
  • 1
    Debanjan, same things that I told Christine. Thanks for your time as well as the ready-to-paste code, again promising I'll type it all in order to understand each step. Will likely return with a feedback this evening. ;) – adry_seme Dec 05 '19 at 07:05
  • @adry_seme Let me know if any questions. – undetected Selenium Dec 05 '19 at 07:08
  • Debanjan! Many thanks to you too, ultimately I worked lots on Christine's code, since the By.XPATH parts made yours a bit less friendly. :) However I appreciate you too suggested to let the script ensure that the page is fully loaded and that the elements are there. – adry_seme Dec 05 '19 at 20:32
  • @adry_seme Sounds great that you have selected an answer which appears more friendly to you :) Congratulations. I could have used (only) _cssSelectors_ as well. Perhaps you had read the entire answer :) Come back to this answer a year later and let me know if you still feel it was less friendly. All the best. – undetected Selenium Dec 05 '19 at 20:42