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 : 문서 내의 앵커 등 조각 지정
- URL의 분해, 조립, 변경 및 URL 문자 인코딩, 디코딩 처리하는 함수 제공
- 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'))
다음 예제는 ProxyHandler 및 ProxyBasicAuthHandler 클래스를 사용하여 프록시 서버를 통과해서 웹 서버로 요청을 보내는 프로그램이다. 여기서 프록시 서버란 클라이언트가 자신을 통해서 다른 네트워크 서비스에 간접적으로 접속할 수 있게 해주는 컴퓨터 시스템이나 응용 프로그램을 가리킨다. (서버와 클라이언트 사이에 중계기)
-
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'))
- 주어진 URL에서 데이터를 가져오는 기본 기능 제공
- 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()
- urllib.request보다 저수준의 더 세밀한 기능이 필요한 경우 http.client 모듈 사용 (ex. GET, POST 이외의 요청, 요청 헤더와 바디 사이에 타이머를 두어 시간 지연 등등)
'파이썬-장고' 카테고리의 다른 글
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 |