각종 버그 🐞/Python

[Python] requests 패키지의 ConnectionResetError(104, 'Connection reset by peer')

hellonero 2020. 7. 24. 18:12

python의 requests 패키지를 사용하다가 보면 간혹 connection reset by peer라는 내용의 104 에러가 발생하곤 합니다. 소켓 연결 실패 시에 생기는 에러인 것으로 알고 있는데, 1시간 가량의 구글링에도 답을 찾지 못하다가 header를 추가하는 방식으로 해결해서 그 과정을 정리해 두려고 합니다.

 

문제 상황은 requests 패키지의 get 함수를 사용해 크롤링을 진행하려다가 발생했습니다. 아마 다들 비슷하실 것 같은데요, 구체적으로는 다음의 코드를 실행하다가 발생했습니다.

 

import requests

r = requests.get("http://patft.uspto.gov/")

 

에러 내용은 다음과 같았습니다.

Traceback (most recent call last):
  File "/opt/anaconda/lib/python3.6/site-packages/urllib3/connectionpool.py", line 672, in urlopen
    chunked=chunked,
  File "/opt/anaconda/lib/python3.6/site-packages/urllib3/connectionpool.py", line 421, in _make_request
    six.raise_from(e, None)
  File "<string>", line 3, in raise_from
  File "/opt/anaconda/lib/python3.6/site-packages/urllib3/connectionpool.py", line 416, in _make_request
    httplib_response = conn.getresponse()
  File "/opt/anaconda/lib/python3.6/http/client.py", line 1354, in getresponse
    response.begin()
  File "/opt/anaconda/lib/python3.6/http/client.py", line 307, in begin
    version, status, reason = self._read_status()
  File "/opt/anaconda/lib/python3.6/http/client.py", line 268, in _read_status
    line = str(self.fp.readline(_MAXLINE + 1), "iso-8859-1")
  File "/opt/anaconda/lib/python3.6/socket.py", line 586, in readinto
    return self._sock.recv_into(b)
ConnectionResetError: [Errno 104] Connection reset by peer

....중략....

  File "/opt/anaconda/lib/python3.6/site-packages/requests/sessions.py", line 643, in send
    r = adapter.send(request, **kwargs)
  File "/opt/anaconda/lib/python3.6/site-packages/requests/adapters.py", line 498, in send
    raise ConnectionError(err, request=request)
requests.exceptions.ConnectionError: ('Connection aborted.', ConnectionResetError(104, 'Connection reset by peer'))

 

서버컴퓨터에서 실행해도 안되고 로컬 컴퓨터에서 실행해도 안되며 네트워크 환경을 바꿔도 안되는 것을 보니 해당 웹페이지에서 아무런 정보없이 요청하는 것에 대해서는 차단하는 것으로 생각되었습니다. 하지만, 브라우저를 통해 해당 페이지를 들어가는 것은 허용되니 브라우저의 헤더를 요청시에 추가하여 정보를 다운로드 하였습니다.

 

크롬을 키고 `command+shift+I`를 누르고 개발자 도구를 켜봅시다. (윈도우에서는 F12) 그리고 `Network` 탭에 들어가서 좌측에 불러와지는 파일들 중 아무거나 클릭해서 `headers`의 가장 아랫부분을 보면 `User-Agent`를 확인할 수 있습니다. 여기있는 정보를 `headers`로 추가하면 성공적으로 get 요청을 할 수 있습니다.

 

 

빨간 박스의 내용들을 복사하여 다음과 같이 headers 딕셔너리를 작성한 뒤, GET 메소드의 parameter로 추가하여 요청하면 정상적으로 요청이 옵니다.

import requests

# 요청 헤더 추가
headers = {"user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.89 Safari/537.36"}
r = requests.get("http://patft.uspto.gov/", headers=headers)

 

+ 추가) 혹은 일시적으로 여러분의 IP의 요청을 차단한 것일 수 있습니다. 한 5~10분 정도 기다린 뒤 다시 시도하면 가능한 경우도 많습니다!

 

*주의: 프로그램을 통한 get 요청을 차단하는 것은 여러가지 이유가 있을 수 있으니, 꼭 크롤링을 할 때는 항상 이 점에 유의해서 진행해 주시길 바랍니다.