[Python] Selenium Stucks / Hangs at Login

Discussão em 'Python' iniciado por Stack, Março 18, 2025.

  1. Stack

    Stack Membro Participativo

    I am trying to perform an automatic login with Selenium. My code keeps getting stuck at password_field.send_keys(Keys.RETURN): The browser window accepts that the data has been entered and return has been pressed, but then the page loads and stays in this mode forever without going any further. The lines after this are therefore not executed. I have already written the code so that password_field.send_keys(Keys.RETURN) and the remaining part are separated and it runs asynchronously, but the same problem occurs.

    import requests
    import base64
    import secrets
    import hashlib
    import webbrowser
    from http.server import HTTPServer, BaseHTTPRequestHandler
    from urllib.parse import urlparse, parse_qs

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

    # Generate PKCE code verifier and challenge (recommended for public clients)
    def generate_pkce_pair():
    code_verifier = secrets.token_urlsafe(64)
    code_challenge = (
    base64.urlsafe_b64encode(hashlib.sha256(code_verifier.encode()).digest())
    .decode()
    .rstrip("=")
    )
    return code_verifier, code_challenge


    # Callback handler to receive the authorization code
    class CallbackHandler(BaseHTTPRequestHandler):
    def do_GET(self):
    self.send_response(200)
    self.send_header("Content-Type", "text/html")
    self.end_headers()

    # Extract authorization code from URL query parameters
    query_components = parse_qs(urlparse(self.path).query)

    if "code" in query_components:
    # Store the auth code in the server instance
    self.server.auth_code = query_components["code"][0]

    # Display success message to the user
    self.wfile.write(
    b"<html><body><h1>Authentication successful!</h1><p>You can close this window now.</p></body></html>"
    )
    else:
    # Handle error or cancel
    self.wfile.write(
    b"<html><body><h1>Authentication failed!</h1><p>No authorization code received.</p></body></html>"
    )
    self.server.auth_code = None

    # Signal that we have processed the callback
    self.server.handled = True


    def get_webpage_resp():

    # Generate PKCE code pair
    code_verifier, code_challenge = generate_pkce_pair()

    # Create the authorization URL
    auth_url = (
    f"{auth_endpoint}"
    f"?client_id={CLIENT_ID}"
    f"&response_type=code"
    f"&redirect_uri={REDIRECT_URI}"
    f"&scope={SCOPE}"
    f"&code_challenge={code_challenge}"
    f"&code_challenge_method=S256"
    f"&state={secrets.token_urlsafe(16)}" # State parameter to prevent CSRF
    )

    # Replace 'your_path_to_webdriver' with the path to your WebDriver executable
    driver = webdriver.Chrome()

    # Open the webpage
    driver.get(auth_url)

    # Fill out form fields by finding them by name, id, or other attributes
    username_field = driver.find_element(By.ID, 'username')
    password_field = driver.find_element(By.ID, 'password')

    username_field.send_keys('blabla_user')
    password_field.send_keys('blabla_pwd')

    # Start local server to receive the callback
    server = HTTPServer(("localhost", 8000), CallbackHandler)
    server.auth_code = None
    server.handled = False

    # Send the Enter/Return key to any of the form fields
    password_field.send_keys(Keys.RETURN)

    # Wait for the callback to be processed
    print("Waiting for authentication callback...")
    while not server.handled:
    server.handle_request()

    # Close the browser
    driver.quit()

    auth_code = server.auth_code
    if not auth_code:
    print("Authentication failed: No authorization code received")
    return

    print(f"Authorization code received: {auth_code}")

    # Exchange authorization code for tokens
    token_data = {
    "grant_type": "authorization_code",
    "code": auth_code,
    "redirect_uri": REDIRECT_URI,
    "client_id": CLIENT_ID,
    "code_verifier": code_verifier,
    }

    # Add client secret for confidential clients
    headers = {"Content-Type": "application/x-www-form-urlencoded"}
    if CLIENT_SECRET:
    token_data["client_secret"] = CLIENT_SECRET

    # Request tokens
    response = requests.post(token_endpoint, data=token_data, headers=headers)

    if response.status_code == 200:
    tokens = response.json()
    print("Authentication successful!")
    print(f"Access Token: {tokens['access_token'][:20]}...")

    if "refresh_token" in tokens:
    print(f"Refresh Token: {tokens['refresh_token'][:20]}...")

    # Now you can use the access token to call your API
    # Example API call:
    api_response = requests.get(
    "https://some-adress",
    headers={"Authorization": f"Bearer {tokens['access_token']}"},
    )
    print(api_response.text)

    else:
    print(f"Token request failed: {response.status_code}")
    print(response.text)

    return response


    If I wait, I get the following error message:

    ReadTimeoutError Traceback (most recent call last)
    Cell In[2], line 1
    ----> 1 get_webpage_resp()

    File /media/tw/Daten/Peak/locust/oauth_webpage_click_simulator.py:110, in get_webpage_resp()
    103 server.handled = False
    105 # muss gemacht werden, sonst hängt die Seite
    106 #driver.set_page_load_timeout(10)
    107 # driver.refresh()
    108
    109 # Send the Enter/Return key to any of the form fields
    --> 110 password_field.send_keys(Keys.RETURN)
    112 driver.get(REDIRECT_URI)
    114 # Wait for the callback to be processed

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/webelement.py:303, in WebElement.send_keys(self, *value)
    300 remote_files.append(self._upload(file))
    301 value = tuple("\n".join(remote_files))
    --> 303 self._execute(
    304 Command.SEND_KEYS_TO_ELEMENT, {"text": "".join(keys_to_typing(value)), "value": keys_to_typing(value)}
    305 )

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/webelement.py:572, in WebElement._execute(self, command, params)
    570 params = {}
    571 params["id"] = self._id
    --> 572 return self._parent.execute(command, params)

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/webdriver.py:427, in WebDriver.execute(self, driver_command, params)
    424 elif "sessionId" not in params:
    425 params["sessionId"] = self.session_id
    --> 427 response = self.command_executor.execute(driver_command, params)
    428 if response:
    429 self.error_handler.check_response(response)

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py:404, in RemoteConnection.execute(self, command, params)
    402 trimmed = self._trim_large_entries(params)
    403 LOGGER.debug("%s %s %s", command_info[0], url, str(trimmed))
    --> 404 return self._request(command_info[0], url, body=data)

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/selenium/webdriver/remote/remote_connection.py:428, in RemoteConnection._request(self, method, url, body)
    425 body = None
    427 if self._client_config.keep_alive:
    --> 428 response = self._conn.request(method, url, body=body, headers=headers, timeout=self._client_config.timeout)
    429 statuscode = response.status
    430 else:

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/_request_methods.py:143, in RequestMethods.request(self, method, url, body, fields, headers, json, **urlopen_kw)
    135 return self.request_encode_url(
    136 method,
    137 url,
    (...)
    140 **urlopen_kw,
    141 )
    142 else:
    --> 143 return self.request_encode_body(
    144 method, url, fields=fields, headers=headers, **urlopen_kw
    145 )

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/_request_methods.py:278, in RequestMethods.request_encode_body(self, method, url, fields, headers, encode_multipart, multipart_boundary, **urlopen_kw)
    274 extra_kw["headers"].setdefault("Content-Type", content_type)
    276 extra_kw.update(urlopen_kw)
    --> 278 return self.urlopen(method, url, **extra_kw)

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/poolmanager.py:443, in PoolManager.urlopen(self, method, url, redirect, **kw)
    441 response = conn.urlopen(method, url, **kw)
    442 else:
    --> 443 response = conn.urlopen(method, u.request_uri, **kw)
    445 redirect_location = redirect and response.get_redirect_location()
    446 if not redirect_location:

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:841, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
    838 elif isinstance(new_e, (OSError, HTTPException)):
    839 new_e = ProtocolError("Connection aborted.", new_e)
    --> 841 retries = retries.increment(
    842 method, url, error=new_e, _pool=self, _stacktrace=sys.exc_info()[2]
    843 )
    844 retries.sleep()
    846 # Keep track of the error for the retry warning.

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/util/retry.py:474, in Retry.increment(self, method, url, response, error, _pool, _stacktrace)
    471 elif error and self._is_read_error(error):
    472 # Read retry?
    473 if read is False or method is None or not self._is_method_retryable(method):
    --> 474 raise reraise(type(error), error, _stacktrace)
    475 elif read is not None:
    476 read -= 1

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/util/util.py:39, in reraise(tp, value, tb)
    37 if value.__traceback__ is not tb:
    38 raise value.with_traceback(tb)
    ---> 39 raise value
    40 finally:
    41 value = None # type: ignore[assignment]

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:787, in HTTPConnectionPool.urlopen(self, method, url, body, headers, retries, redirect, assert_same_host, timeout, pool_timeout, release_conn, chunked, body_pos, preload_content, decode_content, **response_kw)
    784 response_conn = conn if not release_conn else None
    786 # Make the request on the HTTPConnection object
    --> 787 response = self._make_request(
    788 conn,
    789 method,
    790 url,
    791 timeout=timeout_obj,
    792 body=body,
    793 headers=headers,
    794 chunked=chunked,
    795 retries=retries,
    796 response_conn=response_conn,
    797 preload_content=preload_content,
    798 decode_content=decode_content,
    799 **response_kw,
    800 )
    802 # Everything went great!
    803 clean_exit = True

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:536, in HTTPConnectionPool._make_request(self, conn, method, url, body, headers, retries, timeout, chunked, response_conn, preload_content, decode_content, enforce_content_length)
    534 response = conn.getresponse()
    535 except (BaseSSLError, OSError) as e:
    --> 536 self._raise_timeout(err=e, url=url, timeout_value=read_timeout)
    537 raise
    539 # Set properties that are used by the pooling layer.

    File ~/miniconda3/envs/conenv_dat_science/lib/python3.12/site-packages/urllib3/connectionpool.py:367, in HTTPConnectionPool._raise_timeout(self, err, url, timeout_value)
    364 """Is the error actually a timeout? Will raise a ReadTimeout or pass"""
    366 if isinstance(err, SocketTimeout):
    --> 367 raise ReadTimeoutError(
    368 self, url, f"Read timed out. (read timeout={timeout_value})"
    369 ) from err
    371 # See the above comment about EAGAIN in Python 3.
    372 if hasattr(err, "errno") and err.errno in _blocking_errnos:

    ReadTimeoutError: HTTPConnectionPool(host='localhost', port=33877): Read timed out. (read timeout=120)

    Continue reading...

Compartilhe esta Página