[Python] HttpConnection(requests 모듈)로 웹 서버에 접속하는 방법


Development note/Python  2020. 1. 30. 09:00

안녕하세요. 명월입니다.


이 글은 Python에서 HttpConnection(requests 모듈)로 웹 서버에 접속하는 방법에 대한 글입니다.


예전에 java나 C#에서 HttpConnection을 이용해서 웹 서버에 접속하는 방법에 대해 설명한 적이 있습니다.

링크 - [Java] HttpUrlConnection을 이용해서 웹 페이지를 가져오기


웹서버와 브라우져의 통신은 요청과 응답 구조로 되어 있습니다. 요청은 호스트 주소 포함해서 페이지를 요청하는 것이고, 응답은 요청에 대한 응답 메시지(해더)와 html를 브라우져로 보내주는 것입니다.

브라우져에서 javascript가 실행되고 CSS style에 맞추어서 화면이 보여지는 것은 브라우져의 랜더링 역할일 뿐이지 서버와 브라우져간에 통신은 String(byte[]) 형식으로 된 것을 주고 받는 게 전부입니다.

로컬에 PHP로 간단한 예제 소스를 작성하고 python으로 request 요청하고 응답을 받아 보겠습니다.

<?php	
  error_reporting(E_ALL & ~E_NOTICE);
  // Get 방식의 경우 파라미터에서 주소를 가져온다.
  echo "GET - ".$_GET["param"];
?>
import requests;

# 접속 url
url = 'http://localhost/';
# requests로 직접 접속도 가능합니다만 요청 사항을 다루려면 세션을 만들어야 합니다.
with requests.Session() as session:
  # proxy환경일 경우 trust_env를 False로 해야 한다.
  # session.trust_env = False;
  # get방식으로 파라미터의 param의 데이터를 넣고 요청한다.
  with session.get(url, params = {'param': 'query string test'}) as response:
    # 요청시의 헤더(딕셔너리)
    print("request headers - " + str(session.headers));
    
    # 응답시의 헤더(딕셔너리)
    print("response headers - " + str(response.headers));
    # byte형식의 응답 본문 데이터
    print("response content - " + str(response.content));
    # str형식의 응답 본문 데이터
    print("response text - " + str(response.text));
    # 현 세션의 쿠키 설정
    print("response cookies - " + str(response.cookies));
    # 본문 인코딩 방식
    print("response encoding - " + str(response.encoding));
    # 응답 성공(200) 인지
    print("response ok - " + str(response.ok));
    # 응답 코드
    print("response status_code - " + str(response.status_code));
    # 요청시의 url
    print("response url - " + str(response.url));

python으로 웹 서버를 접속하는 건 매우 간단합니다. requests의 모듈로 부터 세션을 받고 그 세션 안에서 localhost로 요청을 보내고 응답한 결과를 받았습니다.

응답 결과는 headers와 text나 content가 가장 중요한 데이터입니다.

text의 결과를 보시면 param의 키로 query string test를 보냈는데, 위 PHP 소스의 결과 대로 GET - query string test의 결과가 나왔습니다.


이번에는 조금 더 복잡하게 post방식으로 session값을 넣고 get방식으로 값을 취득해 오는 방법을 설명하겠습니다.

<?php
  // PHP 세션을 개시한다. (브라우져로 Set-Cookie로 session key가 발급된다.)
  session_start();
  error_reporting(E_ALL & ~E_NOTICE);
  // POST 방식일 경우
  if ($_SERVER["REQUEST_METHOD"] == "POST") {
      // POST의 파라미터 DATA를 세션 DATA에 넣는다.
      $_SESSION["DATA"] = $_POST["DATA"];
      echo "OK";
  } else {
      // GET방식일 경우 세션의 DATA값을 출력한다.
      echo $_SESSION["DATA"];
  }
?>
import requests;

# 접속 url
url = 'http://localhost/';
# requests로 직접 접속도 가능합니다만 요청 사항을 다루려면 세션을 만들어야 합니다.
with requests.Session() as session:
  # 먼저 post방식으로 DATA 파라미터에 Hello world의 값을 넣습니다.
  with session.post(url, data = {'DATA': 'Hello world'}) as response:
    # str형식의 응답 본문 데이터
    print("response text - " + str(response.text));
    # 응답 헤더
    print("response headers - " + str(response.headers));
    # 응답 쿠키
    print("response cookies - " + str(response.cookies));
    
    # 응답 온 쿠키 값을 cookies의 변수에 넣는다.
    cookies = response.cookies;
    # cookies를 딕셔너리 타입을 넣어도 된다.
    #cookies = {'PHPSESSID': response.cookies["PHPSESSID"]}
    # 요청한 헤더값을 headers의 변수에 넣는다.
    headers = session.headers;
  # 두번째 요청에서는 따로 cookie 설정을 하지 않아도 같은 session안이면 cookie가 유지된다.
  with session.get(url) as response:
    # 그러므로 결과는 Hello world가 나온다.
    print("response text - " + str(response.text));

# 여기는 위 request 세션과 다르다.
with requests.Session() as session:
  # 세션을 유지하려면 쿠키를 설정해야 한다.
  with session.get(url, headers= headers, cookies = cookies) as response:
    # 그러므로 결과는 Hello world가 나온다.
    print("response text - " + str(response.text));

Python에서는 requests를 사용할 때, 저 Session만 유지를 잘하면 따로 쿠키의 설정 필요없이 세션 유지가 가능합니다.(C#과 java도 이런 기능이 있는지 살펴봐야 겠네요...)

그렇다면 응용으로 일반 웹 서버에서도 login을 하고 나서 값을 가져오는게 가능하겠네요...


request의 함수는 post, get이 가장 많이 사용되는 함수입니다.

response는 사양에 따라 여러 함수 및 변수를 사용하므로 아래의 표에 정리를 해 두었습니다.

함수 및 프로퍼티 설명
apparent_encoding 인코딩 값으로 반환
content 응답 내용을 바이트 단위로 반환합니다
cookies 서버에서 보낸 쿠키와 함께 CookieJar 객체를 반환합니다.
elapsed 요청을 보낸 후 응답 도착 시간이 경과 한 timedelta 객체를 반환합니다.
encoding r.text를 해독하는 데 사용되는 인코딩을 반환합니다.
headers 응답 헤더의 딕셔너리를 반환합니다
history 요청 히스토리 (url)를 보유한 응답 오브젝트 목록을 리턴합니다.
is_permanent_redirect 응답이 영구적으로 리디렉션 된 URL이면 True를, 그렇지 않으면 False를 반환합니다.
is_redirect 응답이 리디렉션 된 경우 True를, 그렇지 않으면 False를 반환합니다.
links 헤더 링크를 반환
next 리디렉션에서 다음 요청에 대한 PreparedRequest 객체를 반환합니다.
ok status_code가 200보다 작 으면 True를, 그렇지 않으면 False를 반환합니다.
reason 상태 코드에 해당하는 텍스트를 반환합니다.
request 이 응답을 요청한 요청 오브젝트를 리턴합니다.
status_code 상태를 나타내는 숫자를 리턴합니다 (200은 OK, 404는 Not Found)
text 응답 내용을 유니 코드로 반환
url 응답의 URL을 반환합니다.
close() 서버와의 연결을 닫습니다.
iter_content() 응답을 반복
iter_lines() 응답 라인을 반복합니다.
json() 결과의 JSON 객체를 반환합니다 (결과가 JSON 형식으로 작성된 경우 오류가 발생하지 않은 경우)
raise_for_status() 오류가 발생하면이 메소드는 HTTPError 객체를 반환합니다.

웹 서버를 접속하는 HttpConnection 객체는 Java와 C#, PHP도 있었고 거의 모든 언어에서 비슷한 라이브러리가 존재합니다.

개인적으로 보면 Python의 requests모듈이 세션을 유지하는 방법이라던가, json()함수처럼 자동으로 json형식을 반환해 주는 함수라던가 등등 좀 더 편리하게 구성되어 있는 것 같습니다. 로컬 스크립트로 자주 사용하는 언어인 만큼 requests로 정보를 자동으로 수집해오는 스크래핑 봇이던가 크로링등을 만들면 편하게 쓸 수 있지 않을까 생각 됩니다.

참조 - https://requests.readthedocs.io/en/master/api/

참조 - https://www.w3schools.com/python/ref_requests_response.asp

참조 - https://stackoverflow.com/questions/40430799/


여기까지 Python에서 HttpConnection(requests 모듈)로 웹 서버에 접속하는 방법에 대한 설명이었습니다.


궁금한 점이나 잘못된 점이 있으면 댓글 부탁드립니다.