2025. 3. 6. 17:52ㆍIT&모바일&컴퓨터
셀레니움으로 웹페이지를 다루는 프로그램을 작성하다 다음과 같은 에러를 만나게되었다.
1. 웹 드라이버 사용중 에러 발견
캡챠문구를 처리하고 난 다음에 갑자기 에러가 발생하는 데다가, urllib3라는 접두어가 있어서, 웹에서 에러가 난 줄 알았다. (왜냐면 원래 잘 작동하던 웹페이지 컨트롤이었으니까)
Traceback (most recent call last):
File "D:\test.py", line 106, in <module>
print("windows :", driver.window_handles, "current window :", driver.current_window_handle)
File "D:\selenium1\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 494, in window_handles
return self.execute(Command.W3C_GET_WINDOW_HANDLES)["value"]
File "D:\selenium1\lib\site-packages\selenium\webdriver\remote\webdriver.py", line 345, in execute
response = self.command_executor.execute(driver_command, params)
File "D:\selenium1\lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 302, in execute
return self._request(command_info[0], url, body=data)
File "D:\selenium1\lib\site-packages\selenium\webdriver\remote\remote_connection.py", line 322, in _request
response = self._conn.request(method, url, body=body, headers=headers)
File "D:\selenium1\lib\site-packages\urllib3\request.py", line 74, in request
return self.request_encode_url(
File "D:\selenium1\lib\site-packages\urllib3\request.py", line 96, in request_encode_url
return self.urlopen(method, url, **extra_kw)
File "D:\selenium1\lib\site-packages\urllib3\poolmanager.py", line 376, in urlopen
response = conn.urlopen(method, u.request_uri, **kw)
File "D:\selenium1\lib\site-packages\urllib3\connectionpool.py", line 815, in urlopen
return self.urlopen(
File "D:\selenium1\lib\site-packages\urllib3\connectionpool.py", line 815, in urlopen
return self.urlopen(
File "D:\selenium1\lib\site-packages\urllib3\connectionpool.py", line 815, in urlopen
return self.urlopen(
File "D:\selenium1\lib\site-packages\urllib3\connectionpool.py", line 787, in urlopen
retries = retries.increment(
File "D:\selenium1\lib\site-packages\urllib3\util\retry.py", line 592, in increment
raise MaxRetryError(_pool, url, error or ResponseError(cause)) urllib3.exceptions.MaxRetryError: HTTPConnectionPool(host='localhost', port=8340): Max retries exceeded with url: /session/932b4090753ba422f693cd6a6bb1d7ca/window/handles (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x000001E67FAD8DF0>: Failed to establish a new connection: [WinError 10061] 대상 컴퓨터에서 연결을 거부했으므로 연결하지 못했습니다'))
2. 웹 드라이버 사용중 발견된 에러의 위치
에러가 난 부분을 확인했더니, 아래서 lIne 7 부분에서 장시간 기다렸다가 위의 에러가 발생하는 것이었다.
1: try:
2: wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#capImg")))
3: except :
4: print("Not found capImg")
5:
6:
7: print(driver.window_handles)
8: driver.switch_to.window( driver.window_handles[0])
Line7은 driver중에 window 핸들을 print해보는 것인데, 여기서 에러가 난다는 것이 이해가 되지 않았다.
Line8에서 에러난 것이 알수 없는 이유로 7에서 에러난 것으로 잘 못 표시된 것은 아닌가 하는 비상식적인 마음에, 8번을 #으로 코멘트 처리해보았지만 결과는 같았다.
3. 코드수정 테스트
1에서 4번의 구분을 다 코멘트 처리해보았더니, 왠 걸 에러없이 정상으로 작동된다???
O My?
4. 에러 trace 출력
음... 이해가 안되지만, 에러가 무엇인지 출력시켜본다(traceback을 import 해야한다). 이 방법을 알았지만, 나름의 고집때문에 실제로 적용해보기까지는 오래걸렸다.
try에서 에러난거는 except에서 catch되었으니까, 그 다음 윈도우 핸들들 출력에서 에러는 날 수가 없어!!!
.. import traceback
1: try:
2: wait.until(EC.visibility_of_element_located((By.CSS_SELECTOR, "#capImg")))
3: except Exception:
4: print("--- [ERROR] : Failed to find capImg ---")
5: err_exc=traceback.format_exc()
6: print(err_exc)
7:
8: print(driver.window_handles)
9: driver.switch_to.window( driver.window_handles[0])
그랬더니 아래와 같이 에러구문들이 직접적으로 출력된다.
--- [ERROR] : Failed to find capImg ---
Traceback (most recent call last):
File "D:.
....
\lib\site-packages\urllib3\connectionpool.py", line 444, in _make_request
httplib_response = conn.getresponse()
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 1377, in getresponse
response.begin()
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 320, in begin
version, status, reason = self._read_status()
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\http\client.py", line 281, in _read_status
line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
File "C:\Users\USER\AppData\Local\Programs\Python\Python39\lib\socket.py", line 704, in readinto
return self._sock.recv_into(b)
ConnectionResetError: [WinError 10054] 현재 연결은 원격 호스트에 의해 강제로 끊겼습니다

5. 이제서야 에러가 이해됨(항상 이럼)
이제서야, 에러구문을 보니 이해가 된다. 이미 wait구문에서 없는 window에 접근하는 바람에 driver와의 연결이 끊겨져버려서, 그 후 driver.window 핸들에 접근 자체가 안되었다는 것.
그래서 driver.window_handles에서 에러가 날 경우를 찾아보니, 다음과 같다.
현재 창이 닫혔거나 존재하지 않을 때 → NoSuchWindowException
웹 드라이버가 종료된 상태일 때 → WebDriverException
네트워크 문제로 연결이 끊길 때 → MaxRetryError
세션이 종료된 상태에서 접근할 때 → InvalidSessionIdException
윈도우 핸들이 유효하지 않을 때 → StaleElementReferenceException
그중에서도 ConnectionResetError 가 발생하는 경우도 찾아보니,
📌 에러 설명: ConnectionResetError: [WinError 10054] 현재 연결은 원격 호스트에 의해 강제로 끊겼습니다
원인: 원격 호스트 (예: 웹 서버나 WebDriver)가 강제로 연결을 끊었을 때 발생합니다. 이는 다음과 같은 이유로 발생할 수 있습니다:
웹 드라이버가 비정상 종료 (예: driver.quit() 없이 종료됨).
네트워크 장애 (예: VPN, 방화벽, 인터넷 끊김).
서버의 제한 (짧은 시간 내 다수 요청 시 차단).
타임아웃 초과 (오래 걸리는 요청 시). HTTP/HTTPS 설정 불일치.
6. 에러의 복구 방향
Ok! 이제 에러를 복구해보자.
그런데 이 에러를 try except으로 받으려고 했더니 다른 에러들이 연달아 나서 잡기가 쉽지 않네?
ConnectionResetError에러의 예외처리 다음과 같다.
📌 요약
ConnectionResetError 직접 처리 → 가장 구체적
OSError 처리 → 포괄적으로 처리
urllib3 예외 처리 → Selenium이 urllib3를 사용할 때
socket 예외 처리 → 네트워크 문제 직접 처리
일반적으로 ConnectionResetError 가 나지 않도록 하려면 다음과 같은 방법들이 추천된다.
📌 요약
네트워크 일시적 장애 → 재시도 루프 사용.
세션 종료 → 새로운 driver 생성 필요.
타임아웃 → set_page_load_timeout 설정.
IP 차단 → 프록시 설정.
keep_alive 비활성화.
우선은 capImg를 찾지 말고, 그전에 윈도우 갯수를 파악하여 창이 이미 닫혔는지 파악한 다음 진행하도록 하여 해결 하였다(에러회피). (참고로, 이미 연결이 끊어진 세션에 재접속은 불가능해서, 에러난이후 이어가려면 driver.quit이후 새로 접근해야한다)