파이썬-장고

파이썬 웹 표준 라이브러리

threegopark 2021. 7. 3. 15:32
728x90

웹 표준 라이브러리 구성

  • urllib 패키지
    • 웹 클라이언트를 작성하는 데 필요한 모듈
    • http서버뿐만 아니라 FTP 서버 및 로컬 파일 등을 처리하는데 공통적으로 필요한 함수와 클래스 제공
    • 주로 URL 처리와 서버 액세스 관련 API 제공
    • http.client 모듈의 API를 한 번 더 추상화하여 조금 더 쉬운 고수준의 API 제공
  • http 패키지
    • 서버용 & 클라이언트용 라이브러리로 구성
  • 웹 서버 프로그래밍(Web Framework)
    • 웹 프레임워크, 사용자 프로그램과 저수준의 http.server 라이브러리 중간에 위치하여 개발 지원 (+확장)

 

 

웹 클라이언트 라이브러리


= 웹 서버에 요청을 보내는 모든 애플리케이션 ( =웹 클라이언트)

 

  • urllib.parse 모듈
    • URL의 분해, 조립, 변경  URL 문자 인코딩, 디코딩 처리하는 함수 제공
      from urllib.parse import urlparse
      
      result = urlparse("http://www.python.org:80/guido/python.html;philosophy?overall=3#n10")
      result
    • urlparse() 함수는 URL을 파싱한 결과로 ParseResult 인스턴스 반환
      • scheme : URL에 사용된 프로토콜
      • netloc : 네트워크 위치, user:password@host:port 형식 (http 프로토콜인 경우 host:port 형식)
      • path : 파일, 애플리케이션의 경로
      • params : 매개변수 (사용 x)
      • query : 질의 문자열 (매개변수), 앰퍼샌드(&)로 구분된 "이름=값" 쌍 형식으로 표시
      • fragment : 문서 내의 앵커 등 조각 지정

  • urllib.request 모듈
    • 주어진 URL에서 데이터를 가져오는 기본 기능 제공
      urlopen(url, data=None, [timeout])​

      • url 인자로 지정한 URL로 연결하고 유사 파일 객체 반환. url 인자는 문자열 or Request 클래스의 인스턴스
      • url에 file 스킴을 지정하면 로컬 파일을 열 수 있음
      • 디폴트 요청 방식은 GET, 웹 서버에 전달할 파라미터가 있으면 질의 문자열을 url 인자에 포함해서 보냄
      • POST로 보내려면 data 인자에 질의 문자열 지정
      • timeout 옵션은 응답을 기다리는 타임아웃 시간을 초 딘위로 표시
    • example 사이트에 접속하는 간단한 웹 클라이언트
      from urllib.request import urlopen
      f = urlopen("http://www.example.com")
      #GET 방식으로 호출
      print(f.read(500).decode('utf-8'))​
       

      POST 방식으로 웹 서버에 요청을 보내기 위해서는 1. urlopen() 함수 호출 시 data 인자 지정 2. data 인자는 URL에 허용된 문자열로 인코딩 3. 유니코드(str) 타입이 아닌 바이트 스트링(bytes) 타입 이어야 한다. 
    •  
    • #POST 방식으로 호출
      data = "language=python&framework=django"
      f = urlopen("http://개인IP주소 및 포트번호", bytes(data, encoding='utf-8'))
      print(f.read(500).decode('utf-8'))


      만일 요청을 보낼 때 요청 헤더를 지정해서 보내고 싶은 경우에는 URL을 지정하는 방식을 변경하면 된다. 즉, url 인자에 문자열 대신에 Request 객체를 지정한다. 지정하고자 하는 Request 객체를 생성하고 add_header()로 헤더를 추가하여 웹 서버에 요청을 보내면 된다. 이때 Request 객체를 생성할 때는 data 인자를 지정해줘야한다.
    • from urllib.request import urlopen, Request
      from urllib.parse import urlencode
      
      url = 'http://127.0.0.1:8000'
      
      #data 인자를 지정해준다.
      data = {
          'name': '김삿갓',
          'email': 'jun@naver.com',
          'url' : 'http://naver.com'
      }
      encData = urlencode(data)
      postData = bytes(encData, encoding='utf-8')
      
      #url인자에 문자열 대신에 request 객체를 지정해준다.
      req = Request(url, data=postData)
      req.add_header('Content-Type', 'application/x-www-form-urlencoded')
      f = urlopen(req)
      print(f.info())
      print(f.read(500).decode('utf-8'))


      조금 더 복잡한 요청을 보내보자. 인증 데이터나 쿠키 데이터를 추가하여 요청을 보내거나, 프록시 서버로 요청하는 등 HTTP의 고급 기능을 포함하여 요청을 보낼 수도 있다. 이를 위해서는 각 기능에 맞는 핸들러 객체를 정의하고 그 핸들러를 build_opener() 함수를 사용하여 오프너에 등록한다. 그런 다음에 오프너의 open() 함수를 호출하면 서버로 요청이 전송된다.
    • from urllib.request import HTTPBasicAuthHandler, build_opener
      
      auth_handler = HTTPBasicAuthHandler()
      #인증 데이터인 realm, user, passwd 등을 포함하여 보내기 위해 HTTPBasicAuthHandler() 활용
      auth_handler.add_password(realm='ksh', user = 'shkim', passwd='shkimadmin', uri = 'http://127.0.0.1:8000/auth/')
      
      #오프너에 등록
      opener = build_opener(auth_handler)
      
      
      resp = opener.open('http://127.0.0.1:8000/auth/')
      print(resp.read().decode('utf-8'))


      urllib.request 모듈에 정의된 HTTPCookieProcessor 클래스를 사용하여 쿠키 데이터를 처리하는 프로그램. 첫 번째 요청에서 쿠키를 담기 위한 준비를 하고 서버로 요청을 보낸다. 두 번째 요청에서는, 첫 번째 응답에서 받은 쿠키를 헤더에 담아서 요청을 보낸다. (만일 두 번째 요청에 쿠키 데이터가 없다면 서버에서 에러로 응답한다.)
    • from urllib.request import Request, HTTPCookieProcessor, build_opener
      
      url = 'http://127.0.0.1:8000/cookie/'
      
      
      #첫 번째 요청, 쿠키를 담을 준비 및 서버 요청 (GET방식)
      cookie_handler = HTTPCookieProcessor() #쿠키 데이터를 처리하는 메서드
      opener = build_opener(cookie_handler) #주어진 순서대로 처리기를 연결하는 build_opener 메서드
      
      req = Request(url)
      res = opener.open(req)
      print(res.info())
      print(res.read().decode('utf-8'))
      
      print('---------------------------------------------------------------')
      #두 번째 요청 (POST방식)
      
      data = 'language=python&framework=django'
      encData = bytes(data, encoding='utf-8')
      
      req = Request(url, encData)
      res = opener.open(req)
      
      print(res.info())
      print(res.read().decode('utf-8'))


      다음 예제는 ProxyHandlerProxyBasicAuthHandler 클래스를 사용하여 프록시 서버를 통과해서 웹 서버로 요청을 보내는 프로그램이다. 여기서 프록시 서버란 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다. (서버와 클라이언트 사이에 중계기)

                                 
    • import urllib.request
      
      url = 'http://www.naver.com'
      proxyServer = 'http://www.proxy.com:3333/'
      
      #방법 1. 프록시 서버를 통해 웹 서버로 요청을 보냄
      proxy_handler = urllib.request.ProxyHandler({'http':proxyServer})
      
      #방법 2. 프록시 서버 설정을 무시하고 바로 웹 서버로 요청을 보냄
      proxy_handler = urllib.request.ProxyHandler({})
      
      #프록시 서버에 대한 인증 처리
      proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
      proxy_auth_handler.add_password('realm', 'host', 'username', 'password')
      
      #2개의 핸들러를 오프너에 등록
      opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
      
      #디폴트 오프너로 지정하면, urlopen() 함수로 요청을 보낼 수 있으므로 디폴트 오프너로 지정
      urllib.request.install_opener(opener)
      
      # opener.open() 대신에 urlopen()을 사용하는 방법
      f = urllib.request.urlopen(url)
      
      print("geturl():", f.getrul())
      print(f.read(300).decode('utf-8'))



  • urllib.request 모듈 예제
    • from urllib.request import urlopen
      from html.parser import HTMLParser
      
      #HTMLParser 클래스 사용 시, 아래와 같이 상속받는 클래스를 정의하고 필요한 내용을 오버라이딩함
      class ImageParser(HTMLParser):
          
          #<img> 태그를 찾기 위해 handler_starttag() 함수를 오버라이딩함
          def handler_starttag(self, tag, attrs):
              if tag != 'img':
                  return
              if not hasattr(self, 'result'):
                  self.result = []
                  
              #<img src> 속성을 찾으면 속성값을 self.result 리스트에 추가함
              for name, value in attrs:
                  if name == 'src':
                      self.result.append(value)
      
      #HTML 문장이 주어지면 HTMLParser 클래스를 사용하여 이미지를 찾고 그 리스트를 출력해주는 def                
      def parse_image(data):
          parser = ImageParser()
          
          #HTML문장을 feed() 함수에 주면 바로 파싱하고 그 결과를 parser.result 리스트에 추가
          parser.feed(data)
          
          #파싱 결과를 set 타입의 dataSet에 모아줌. 만일 중복항복이 있다면 set() 기능에 의해 제거됨
          dataSet = set(x for x in parser.result)
          return dataSet
      
      
      #프로그램의 시작점인 메인함수, www.google.co.kr 사이트를 검색하여 이미지를 찾는 함수
      def main():
          url = "http://www.google.co.kr"
          
          #urllib.request 모듈의 urlopen() 함수를 사용하여 구글 사이트에 접속 후 첫 페이지 내용을 가져옴
          with urlopen(url) as f:
              #사이트의 데이터는 인코딩된 데이터이므로 charset을 통해 인코딩 방식을 알아내어 그 방식으로 디코딩한다.
              charset = f.info().get_param('charset')
              data = f.read().decode(charset)
              
          #이미지를 찾기위해 위에서 정의한 parse_image를 호출함    
          dataSet = parse_image(data)
          
          print("\n>>>>>>>>>Fetch Image from", url)
          print("\n".join(sorted(dataSet)))
      
      #프로그램 시작을 위해 main() 함수 호출    
      if __name__ == '__main__':
          main()
      특정 웹사이트에서 이미지만을 검색하여 그 리스트를 보여주는 프로그램

  • http.client 모듈
    • urllib.request보다 저수준의 더 세밀한 기능이 필요한 경우 http.client 모듈 사용 (ex. GET, POST 이외의 요청, 요청 헤더와 바디 사이에 타이머를 두어 시간 지연 등등)

    • http.client 모듈 사용 시 코딩 순서
      연결 객체 순서 conn=http.client.HTTPConnection("www.python.org")
      요청 보냄 conn.request("GET"."/index.html")
      응답 객체 생성 response = conn.getresponse()
      응답 데이터를 읽음 data = response.read()
      연결 닫음 conn.close()

 

'파이썬-장고' 카테고리의 다른 글

Django (4)  (0) 2021.07.11
Django (3)  (0) 2021.07.07
Django (2)  (0) 2021.07.07
Django (1)  (0) 2021.07.07
웹 프로그래밍의 이해  (0) 2021.06.21