"urllib.request" --- URL을 열기 위한 확장 가능한 라이브러리
***********************************************************

**소스 코드:** Lib/urllib/request.py

======================================================================

"urllib.request" 모듈은 복잡한 세계에서 URL(대부분 HTTP)을 여는 데 도
움이 되는 함수와 클래스를 정의합니다 --- 기본(basic)과 다이제스트 인증
, 리디렉션, 쿠키 등.

더 보기: 더 고수준 HTTP 클라이언트 인터페이스로 Requests 패키지를 권장합니다.

경고:

  On macOS it is unsafe to use this module in programs using
  "os.fork()" because the "getproxies()" implementation for macOS uses
  a higher-level system API. Set the environment variable "no_proxy"
  to "*" to avoid this problem (e.g. "os.environ["no_proxy"] = "*"").

가용성: not WASI.

이 모듈은 웹어셈블리에서 작동하지 않거나 제공되지 않습니다. 자세한 내
용은 웹어셈블리 플랫폼을 참조하세요.

"urllib.request" 모듈은 다음 함수를 정의합니다:

urllib.request.urlopen(url, data=None, [timeout, ]*, context=None)

   유효하고, 올바르게 인코딩된 URL을 포함하는 문자열이나 "Request" 객
   체일 수 있는, *url*을 엽니다.

   *data*는 서버로 전송할 추가 데이터를 지정하는 객체이거나, 그러한 데
   이터가 필요하지 않으면 "None"이어야 합니다. 자세한 내용은 "Request"
   를 참조하십시오.

   urllib.request 모듈은 HTTP/1.1을 사용하고 HTTP 요청에
   "Connection:close" 헤더를 포함합니다.

   선택적 *timeout* 매개 변수는 연결 시도와 같은 연산을 블로킹하기 위
   한 시간제한을 초 단위로 지정합니다 (지정하지 않으면 전역 기본 시간
   제한 설정이 사용됩니다). 이것은 실제로는 HTTP, HTTPS 및 FTP 연결에
   서만 작동합니다.

   *context*가 지정되면, 다양한 SSL 옵션을 기술하는 "ssl.SSLContext"
   인스턴스이어야 합니다. 자세한 내용은 "HTTPSConnection"을 참조하십시
   오.

   이 함수는 항상 *컨텍스트 관리자*로 작동할 수 있고 *url*, *headers*
   및 *status* 프로퍼티를 가진 객체를 반환합니다. 이러한 프로퍼티에 대
   한 자세한 내용은 "urllib.response.addinfourl"을 참조하십시오.

   HTTP 및 HTTPS URL의 경우, 이 함수는 약간 수정된
   "http.client.HTTPResponse" 객체를 반환합니다. 위의 세 가지 새로운
   메서드 외에도, msg 어트리뷰트에는 "HTTPResponse" 설명서에 지정된 대
   로 응답 헤더 대신 "reason" 어트리뷰트와 --- 서버가 반환한 이유 문구
   --- 같은 정보가 포함됩니다.

   For FTP, file, and data URLs, this function returns a
   "urllib.response.addinfourl" object.

   프로토콜 에러 시 "URLError"를 발생시킵니다.

   아무런 처리기도 요청을 처리하지 않으면 "None"이 반환될 수 있습니다
   (기본 설치된 전역 "OpenerDirector"는 "UnknownHandler"를 사용하여 이
   러한 상황이 발생하지 않도록 합니다).

   또한, 프락시 설정이 감지되면 (예를 들어, "http_proxy"와 같은
   "*_proxy" 환경 변수가 설정될 때), "ProxyHandler"가 기본적으로 설치
   되어 프락시를 통해 요청이 처리되도록 합니다.

   파이썬 2.6 및 이전 버전의 레거시 "urllib.urlopen" 함수는 중단되었습
   니다; "urllib.request.urlopen()"는 이전 "urllib2.urlopen"에 해당합
   니다. 딕셔너리 매개 변수를 "urllib.urlopen"에 전달하여 수행되었던
   프락시 처리는 "ProxyHandler" 객체를 사용하여 얻을 수 있습니다.

   기본 오프너는 요청 객체에서 취한 인자 "fullurl", "data", "headers",
   "method"로 감사 이벤트 "urllib.Request"를 발생시킵니다.

   버전 3.2에서 변경: *cafile*과 *capath*가 추가되었습니다.가능하다면
   (즉, "ssl.HAS_SNI"가 참이라면) HTTPS 가상 호스트가 지원됩니다
   .*data*는 이터러블 객체일 수 있습니다.

   버전 3.3에서 변경: *cadefault*가 추가되었습니다.

   버전 3.4.3에서 변경: *context*가 추가되었습니다.

   버전 3.10에서 변경: HTTPS connection now send an ALPN extension
   with protocol indicator "http/1.1" when no *context* is given.
   Custom *context* should set ALPN protocols with
   "set_alpn_protocols()".

   버전 3.13에서 변경: Remove *cafile*, *capath* and *cadefault*
   parameters: use the *context* parameter instead.

urllib.request.install_opener(opener)

   "OpenerDirector" 인스턴스를 기본 전역 오프너로 설치합니다. 오프너
   설치는 urlopen이 해당 오프너를 사용하도록 하려는 경우에만 필요합니
   다; 그렇지 않으면 단순히 "urlopen()" 대신 "OpenerDirector.open()"을
   호출하십시오. 코드는 실제 "OpenerDirector"를 확인하지 않으며, 적절
   한 인터페이스를 가진 클래스면 모두 작동합니다.

urllib.request.build_opener([handler, ...])

   주어진 순서대로 처리기를 연결하는 "OpenerDirector" 인스턴스를 반환
   합니다. *handler*는 "BaseHandler"의 인스턴스이거나 "BaseHandler"의
   서브 클래스(이 경우 매개 변수 없이 생성자를 호출할 수 있어야 합니다
   )일 수 있습니다. 다음과 같은 클래스들의 인스턴스는 *handler*에 그들
   , 그들의 인스턴스 또는 그들의 서브 클래스가 포함되지 않는 한
   *handler* 앞에 있습니다: "ProxyHandler" (프락시 설정이 감지되는 경
   우), "UnknownHandler", "HTTPHandler", "HTTPDefaultErrorHandler",
   "HTTPRedirectHandler", "FTPHandler", "FileHandler",
   "HTTPErrorProcessor".

   파이썬 설치에 SSL 지원이 있으면 (즉, "ssl" 모듈을 임포트 할 수 있으
   면) "HTTPSHandler"도 추가됩니다.

   "BaseHandler" 서브 클래스는 또한 "handler_order" 어트리뷰트를 변경
   하여 처리기 리스트에서 자신의 위치를 수정할 수 있습니다.

urllib.request.pathname2url(path, *, add_scheme=False)

   Convert the given local path to a "file:" URL. This function uses
   "quote()" function to encode the path.

   If *add_scheme* is false (the default), the return value omits the
   "file:" scheme prefix. Set *add_scheme* to true to return a
   complete URL.

   This example shows the function being used on Windows:

      >>> from urllib.request import pathname2url
      >>> path = 'C:\\Program Files'
      >>> pathname2url(path, add_scheme=True)
      'file:///C:/Program%20Files'

   버전 3.14에서 변경: Windows drive letters are no longer converted
   to uppercase, and ":" characters not following a drive letter no
   longer cause an "OSError" exception to be raised on Windows.

   버전 3.14에서 변경: Paths beginning with a slash are converted to
   URLs with authority sections. For example, the path "/etc/hosts" is
   converted to the URL "///etc/hosts".

   버전 3.14에서 변경: The *add_scheme* parameter was added.

urllib.request.url2pathname(url, *, require_scheme=False, resolve_host=False)

   Convert the given "file:" URL to a local path. This function uses
   "unquote()" to decode the URL.

   If *require_scheme* is false (the default), the given value should
   omit a "file:" scheme prefix. If *require_scheme* is set to true,
   the given value should include the prefix; a "URLError" is raised
   if it doesn't.

   The URL authority is discarded if it is empty, "localhost", or the
   local hostname. Otherwise, if *resolve_host* is set to true, the
   authority is resolved using "socket.gethostbyname()" and discarded
   if it matches a local IP address (as per **RFC 8089 §3**). If the
   authority is still unhandled, then on Windows a UNC path is
   returned, and on other platforms a "URLError" is raised.

   This example shows the function being used on Windows:

      >>> from urllib.request import url2pathname
      >>> url = 'file:///C:/Program%20Files'
      >>> url2pathname(url, require_scheme=True)
      'C:\\Program Files'

   버전 3.14에서 변경: Windows drive letters are no longer converted
   to uppercase, and ":" characters not following a drive letter no
   longer cause an "OSError" exception to be raised on Windows.

   버전 3.14에서 변경: The URL authority is discarded if it matches
   the local hostname. Otherwise, if the authority isn't empty or
   "localhost", then on Windows a UNC path is returned (as before),
   and on other platforms a "URLError" is raised.

   버전 3.14에서 변경: The URL query and fragment components are
   discarded if present.

   버전 3.14에서 변경: The *require_scheme* and *resolve_host*
   parameters were added.

urllib.request.getproxies()

   이 도우미 함수는 스킴에서 프락시 서버 URL로 매핑하는 딕셔너리를 반
   환합니다. 먼저 모든 운영 체제에서 대소 문자를 구분하지 않는 방식으
   로 "<scheme>_proxy"라는 변수를 환경에서 스캔하고, 찾을 수 없으면
   macOS의 시스템 구성과 윈도우의 윈도우 시스템 레지스트리에서 프락시
   정보를 찾습니다. 소문자와 대문자 환경 변수가 모두 존재하면 (그리고
   다른 값을 가지면), 소문자가 선호됩니다.

   참고:

     일반적으로 스크립트가 CGI 환경에서 실행 중임을 나타내는 환경 변수
     "REQUEST_METHOD"가 설정되면, 환경 변수 "HTTP_PROXY"(대문자
     "_PROXY")는 무시됩니다. 이 변수는 "Proxy:" HTTP 헤더를 사용하여
     클라이언트가 주입할 수 있기 때문입니다. CGI 환경에서 HTTP 프락시
     를 사용해야 하면, "ProxyHandler"를 명시적으로 사용하거나 변수 이
     름이 소문자(또는 적어도 "_proxy" 접미사)가 되도록 하십시오.

다음과 같은 클래스가 제공됩니다:

class urllib.request.Request(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)

   이 클래스는 URL 요청의 추상화입니다.

   *url*은 유효하고 올바르게 인코딩된 URL을 포함하는 문자열이어야 합니
   다.

   *data*는 서버로 전송할 추가 데이터를 지정하는 객체이거나, 그러한 데
   이터가 필요하지 않으면 "None"이어야 합니다. 현재 HTTP 요청은 *data*
   를 사용하는 유일한 요청입니다. 지원되는 객체 형에는 바이트열, 파일
   류 객체 및 바이트열류 객체의 이터러블이 포함됩니다. "Content-
   Length"와 "Transfer-Encoding" 헤더 필드가 모두 제공되지 않으면,
   "HTTPHandler"는 *data*의 형에 따라 이러한 헤더를 설정합니다.
   "Content-Length"는 바이트열 객체를 보내는 데 사용되는 반면, **RFC
   7230**, 섹션 3.3.1에 지정된 "Transfer-Encoding: chunked"는 파일과
   다른 이터러블을 보내는 데 사용됩니다.

   HTTP POST 요청 메서드의 경우, *data*는 표준 *application/x-www-
   form-urlencoded* 형식의 버퍼여야 합니다. "urllib.parse.urlencode()"
   함수는 매핑이나 2-튜플의 시퀀스를 취하고 이 형식의 ASCII 문자열을
   반환합니다. *data* 매개 변수로 사용되기 전에 바이트열로 인코딩되어
   야 합니다.

   *headers*는 딕셔너리이어야 하며, 각 키와 값을 인자로 사용하여
   "add_header()"가 호출된 것처럼 처리됩니다. 이것은 종종 브라우저가
   자신을 식별하는 데 사용하는 "User-Agent" 헤더 값을 "스푸핑" 하는 데
   사용됩니다 -- 일부 HTTP 서버는 스크립트가 아닌 일반 브라우저에서 오
   는 요청만 허용합니다. 예를 들어, Mozilla Firefox는 자신을
   ""Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127
   Firefox/2.0.0.11""로 식별하는 반면, "urllib"의 기본 사용자 에이전트
   문자열은 ""Python-urllib/2.6"" (파이썬 2.6에서) 입니다. 모든 헤더
   키는 카멜 표기법(camel case)으로 전송됩니다.

   *data* 인자가 있으면 적절한 "Content-Type" 헤더가 포함되어야 합니다
   . 이 헤더가 제공되지 않고 *data*가 "None"이 아니면, "Content-Type:
   application/x-www-form-urlencoded"가 기본값으로 추가됩니다.

   다음 두 인자는 제삼자 HTTP 쿠키를 올바르게 처리하는 데에만 관심이
   있습니다:

   *origin_req_host*는 **RFC 2965**에 의해 정의된 대로 오리진 트랜잭션
   의 요청 호스트여야 합니다. 기본값은
   "http.cookiejar.request_host(self)"입니다. 이것은 사용자가 시작한
   원래 요청의 호스트 이름이나 IP 주소입니다. 예를 들어, HTML 문서의
   이미지에 대한 요청이면, 이미지가 포함된 페이지에 대한 요청의 요청
   호스트여야 합니다.

   *unverifiable*은 **RFC 2965**에서 정의한 대로 요청을 확인할 수 없는
   지를 표시해야 합니다. 기본값은 "False"입니다. 확인할 수 없는 요청은
   사용자에게 URL에 대한 승인 옵션이 없는 요청입니다. 예를 들어, HTML
   문서의 이미지에 대한 요청이고, 사용자에게 이미지의 자동 가져오기를
   승인할 수 있는 옵션이 없으면, 이것은 참이어야 합니다.

   *method*는 사용될 HTTP 요청 메서드를 나타내는 문자열이어야 합니다 (
   예를 들어 "'HEAD'"). 제공되면, 해당 값은 "method" 어트리뷰트에 저장
   되고 "get_method()"에서 사용됩니다. 기본값은 *data*가 "None"이면
   "'GET'"이고, 그렇지 않으면 "'POST'"입니다. 서브 클래스는 클래스 자
   체에서 "method" 어트리뷰트를 설정하여 다른 기본 메서드를 나타낼 수
   있습니다.

   참고:

     data 객체가 콘텐츠를 두 번 이상 (예를 들어 콘텐츠를 한 번만 생성
     할 수 있는 파일이나 이터러블) 전달할 수 없고 요청이 HTTP 리디렉션
     이나 인증을 위해 재시도되는 경우, 요청이 예상대로 작동하지 않습니
     다. *data*는 헤더 바로 다음에 HTTP 서버로 전송됩니다. 라이브러리
     에서 100-continue 예상(expectation)을 지원하지 않습니다.

   버전 3.3에서 변경: "Request.method" 인자가 Request 클래스에 추가됩
   니다.

   버전 3.4에서 변경: 클래스 수준에서 기본 "Request.method"를 지정할
   수 있습니다.

   버전 3.6에서 변경: "Content-Length"가 제공되지 않고 *data*가 "None"
   이나 바이트열 객체가 아닐 때 에러를 발생시키지 앖습니다. 대신 청크
   전송 인코딩(chunked transfer encoding)으로 폴백 합니다.

class urllib.request.OpenerDirector

   "OpenerDirector" 클래스는 서로 연결된 "BaseHandler"들을 통해 URL을
   엽니다. 처리기 연결과 에러 복구를 관리합니다.

class urllib.request.BaseHandler

   이것은 등록된 모든 처리기의 베이스 클래스이며 --- 간단한 등록 메커
   니즘만 처리합니다.

class urllib.request.HTTPDefaultErrorHandler

   HTTP 에러 응답에 대한 기본 처리기를 정의하는 클래스; 모든 응답은
   "HTTPError" 예외로 바뀝니다.

class urllib.request.HTTPRedirectHandler

   리디렉션을 처리하는 클래스.

class urllib.request.HTTPCookieProcessor(cookiejar=None)

   HTTP 쿠키를 처리하는 클래스.

class urllib.request.ProxyHandler(proxies=None)

   요청이 프락시를 거치게 합니다. *proxies*가 제공되면, 프로토콜 이름
   을 프락시 URL로 매핑하는 딕셔너리여야 합니다. 기본값은 환경 변수
   "<protocol>_proxy"에서 프락시 목록을 읽는 것입니다. 프락시 환경 변
   수가 설정되어 있지 않으면, 윈도우 환경에서는 레지스트리의 인터넷 설
   정 섹션에서 프락시 설정을 가져오고, macOS 환경에서는 프락시 정보를
   시스템 구성 프레임워크에서 가져옵니다.

   자동 감지 프락시를 비활성화하려면 빈 딕셔너리를 전달하십시오.

   "no_proxy" 환경 변수를 사용하여 프락시를 통해 도달해서는 안 되는 호
   스트를 지정할 수 있습니다; 설정되면, 쉼표로 구분된 호스트 이름 접미
   사의 목록이어야 하며, 선택적으로 ":port"가 추가됩니다, 예를 들어
   "cern.ch,ncsa.uiuc.edu,some.host:8080".

   참고:

     변수 "REQUEST_METHOD"가 설정되면 "HTTP_PROXY"는 무시됩니다;
     "getproxies()"의 설명서를 참조하십시오.

class urllib.request.HTTPPasswordMgr

   "(realm, uri) -> (user, password)" 매핑 데이터베이스를 유지합니다.

class urllib.request.HTTPPasswordMgrWithDefaultRealm

   "(realm, uri) -> (user, password)" 매핑 데이터베이스를 유지합니다.
   "None" realm은 포괄(catch-all) 영역으로 간주하며 다른 영역에 맞지
   않으면 검색됩니다.

class urllib.request.HTTPPasswordMgrWithPriorAuth

   "uri -> is_authenticated" 매핑 데이터베이스도 포함하는
   "HTTPPasswordMgrWithDefaultRealm"의 변형. BasicAuth 처리기에서
   "401" 응답을 먼저 기다리는 대신 인증 자격 증명을 언제 보낼 것인지
   결정하는 데 사용할 수 있습니다.

   Added in version 3.5.

class urllib.request.AbstractBasicAuthHandler(password_mgr=None)

   원격 호스트와 프락시 모두에서 HTTP 인증을 돕는 믹스인 클래스입니다.
   *password_mgr*이 주어지면 "HTTPPasswordMgr" 과 호환되는 것이어야 합
   니다; 지원해야 하는 인터페이스에 대한 정보는 섹션 HTTPPasswordMgr
   객체를 참조하십시오. *passwd_mgr*이 "is_authenticated"와
   "update_authenticated" 메서드도 제공하면
   (HTTPPasswordMgrWithPriorAuth 객체를 참조하십시오), 처리기는 지정된
   URI에 대해 "is_authenticated" 결과를 사용하여 요청과 함께 인증 자격
   증명을 보낼지를 판별합니다. "is_authenticated"가 URI에 대해 "True"
   를 반환하면, 자격 증명이 전송됩니다. "is_authenticated"가 "False"이
   면, 자격 증명이 전송되지 않으며, 그런 다음 "401" 응답이 수신되면 요
   청이 인증 자격 증명과 함께 다시 전송됩니다. 인증이 성공하면, 이 URI
   에 대해 "is_authenticated"를 "True"로 설정하기 위해
   "update_authenticated"가 호출되어서, 이 URI나 모든 슈퍼 URI에 대한
   후속 요청에 인증 자격 증명이 자동으로 포함됩니다.

   Added in version 3.5: "is_authenticated" 지원이 추가되었습니다.

class urllib.request.HTTPBasicAuthHandler(password_mgr=None)

   원격 호스트와의 인증을 처리합니다. *password_mgr*이 주어지면
   "HTTPPasswordMgr" 과 호환되는 것이어야 합니다; 지원해야 하는 인터페
   이스에 대한 정보는 섹션 HTTPPasswordMgr 객체를 참조하십시오. 잘못된
   인증 스킴(Authentication scheme)을 제시하면 HTTPBasicAuthHandler 가
   "ValueError"를 발생시킵니다.

class urllib.request.ProxyBasicAuthHandler(password_mgr=None)

   프락시와의 인증을 처리합니다. *password_mgr*이 주어지면
   "HTTPPasswordMgr" 과 호환되는 것이어야 합니다; 지원해야 하는 인터페
   이스에 대한 정보는 섹션 HTTPPasswordMgr 객체를 참조하십시오.

class urllib.request.AbstractDigestAuthHandler(password_mgr=None)

   원격 호스트와 프락시 모두에서 HTTP 인증을 돕는 믹스인 클래스입니다.
   *password_mgr*이 주어지면 "HTTPPasswordMgr" 과 호환되는 것이어야 합
   니다; 지원해야 하는 인터페이스에 대한 정보는 섹션 HTTPPasswordMgr
   객체를 참조하십시오.

   버전 3.14에서 변경: Added support for HTTP digest authentication
   algorithm "SHA-256".

class urllib.request.HTTPDigestAuthHandler(password_mgr=None)

   원격 호스트와의 인증을 처리합니다. *password_mgr*이 주어지면
   "HTTPPasswordMgr" 과 호환되는 것이어야 합니다; 지원해야 하는 인터페
   이스에 대한 정보는 섹션 HTTPPasswordMgr 객체를 참조하십시오. 다이제
   스트 인증 처리기와 기본 인증 처리기가 모두 추가되면, 다이제스트 인
   증이 항상 먼저 시도됩니다. 다이제스트 인증이 다시 40x 응답을 반환하
   면, 기본 인증 처리기로 보내 처리됩니다. 이 처리기 메서드는 Digest나
   Basic 이외의 인증 스킴(authentication scheme)이 제공될 때
   "ValueError"를 발생시킵니다.

   버전 3.3에서 변경: 지원되지 않는 인증 스킴에 대해 "ValueError"를 발
   생시킵니다.

class urllib.request.ProxyDigestAuthHandler(password_mgr=None)

   프락시와의 인증을 처리합니다. *password_mgr*이 주어지면
   "HTTPPasswordMgr" 과 호환되는 것이어야 합니다; 지원해야 하는 인터페
   이스에 대한 정보는 섹션 HTTPPasswordMgr 객체를 참조하십시오.

class urllib.request.HTTPHandler

   HTTP URL 열기를 처리하는 클래스.

class urllib.request.HTTPSHandler(debuglevel=0, context=None, check_hostname=None)

   HTTPS URL 열기를 처리하는 클래스. *context*와 *check_hostname*은
   "http.client.HTTPSConnection"과 같은 의미입니다.

   버전 3.2에서 변경: *context*와 *check_hostname*이 추가되었습니다.

class urllib.request.FileHandler

   로컬 파일을 엽니다.

class urllib.request.DataHandler

   데이터 URL을 엽니다.

   Added in version 3.4.

class urllib.request.FTPHandler

   FTP URL을 엽니다.

class urllib.request.CacheFTPHandler

   지연 시간을 최소화하기 위해 열린 FTP 연결의 캐시를 유지하면서, FTP
   URL을 엽니다.

class urllib.request.UnknownHandler

   알 수 없는 URL을 처리하기 위한 포괄적인(catch-all) 클래스.

class urllib.request.HTTPErrorProcessor

   HTTP 에러 응답을 처리합니다.


Request 객체
============

다음 메서드는 "Request"의 공용 인터페이스를 설명하므로, 서브 클래스에
서 모두 재정의될 수 있습니다. 또한 클라이언트가 구문 분석된 요청을 검
사하는 데 사용할 수 있는 몇 가지 공용 어트리뷰트를 정의합니다.

Request.full_url

   생성자에 전달된 원래 URL.

   버전 3.4에서 변경.

   Request.full_url은 setter, getter 및 deleter가 있는 프로퍼티입니다.
   "full_url"을 읽으면 프래그먼트가 있는 원래 요청 URL을 반환합니다 (
   있다면).

Request.type

   URI 스킴.

Request.host

   URI 주체(authority), 일반적으로 호스트이지만 콜론으로 구분된 포트를
   포함할 수도 있습니다.

Request.origin_req_host

   포트가 없는, 요청의 원래 호스트.

Request.selector

   URI 경로. "Request"가 프락시를 사용하면, selector는 프락시로 전달되
   는 전체 URL이 됩니다.

Request.data

   요청의 엔티티 바디, 또는 지정되지 않으면 "None".

   버전 3.4에서 변경: "Request.data"의 값을 변경하면 이제 "Content-
   Length" 헤더가 이전에 설정되거나 계산되었다면 삭제됩니다.

Request.unverifiable

   불리언, **RFC 2965**에서 정의한 대로 요청을 확인할 수 없는지를 나타
   냅니다.

Request.method

   사용할 HTTP 요청 메서드. 기본적으로 값은 "None"입니다. 이는
   "get_method()"가 사용될 메서드의 일반적인 계산을 수행함을 뜻합니다.
   "Request" 서브 클래스의 클래스 수준에서 값을 설정해서 기본값을 제공
   하거나, *method* 인자를 통해 "Request" 생성자에 값을 전달하여 값을
   설정할 수 있습니다 (그래서 "get_method()"의 기본 계산을 무시합니다
   ).

   Added in version 3.3.

   버전 3.4에서 변경: 서브 클래스에서 이제 기본값을 설정할 수 있습니다
   ; 이전에는 생성자 인자를 통해서만 설정할 수 있었습니다.

Request.get_method()

   HTTP 요청 메서드를 나타내는 문자열을 반환합니다. "Request.method"가
   "None"이 아니면, 그 값을 반환하고, 그렇지 않으면 "Request.data"가
   "None"이면 "'GET'"을 반환하거나 그렇지 않으면 "'POST'"를 반환합니다
   . 이것은 HTTP 요청에만 의미가 있습니다.

   버전 3.3에서 변경: get_method는 이제 "Request.method"의 값을 조사합
   니다.

Request.add_header(key, val)

   요청에 다른 헤더를 추가합니다. 헤더는 현재 HTTP 처리기를 제외한 모
   든 처리기에서 무시되며, HTTP 처리기에서는 서버로 전송되는 헤더 리스
   트에 추가됩니다. 같은 이름을 가진 헤더를 두 개 이상 가질 수 없으며,
   *key*가 충돌하는 경우 후속 호출은 이전 호출을 덮어씁니다. 현재, 두
   번 이상 사용될 때 의미가 있는 모든 헤더는 하나의 헤더만 사용하여 같
   은 기능을 얻는 (헤더 별) 방식을 가지므로 HTTP 기능의 손실은 없습니
   다. 이 메서드로 추가된 헤더는 리디렉션 된 요청에도 추가됨에 유의하
   십시오.

Request.add_unredirected_header(key, header)

   리디렉션 된 요청에 추가되지 않을 헤더를 추가합니다.

Request.has_header(header)

   인스턴스에 명명된 헤더가 있는지를 반환합니다 (일반과 리디렉션되지
   않는 것을 모두 확인합니다).

Request.remove_header(header)

   요청 인스턴스에서 명명된 헤더를 제거합니다 (일반과 리디렉션되지 않
   은 헤더 모두).

   Added in version 3.4.

Request.get_full_url()

   생성자에 제공된 URL을 반환합니다.

   버전 3.4에서 변경.

   "Request.full_url"을 반환합니다

Request.set_proxy(host, type)

   프락시 서버에 연결하여 요청을 준비합니다. *host*와 *type*은 인스턴
   스의 것을 대체하고, 인스턴스의 selector는 생성자에 제공된 원래 URL
   이 됩니다.

Request.get_header(header_name, default=None)

   지정된 헤더의 값을 반환합니다. 헤더가 없으면, default 값을 반환합니
   다.

Request.header_items()

   요청 헤더의 튜플 (header_name, header_value) 리스트를 반환합니다.

버전 3.4에서 변경: 3.3부터 폐지된 add_data, has_data, get_data,
get_type, get_host, get_selector, get_origin_req_host 및
is_unverifiable 요청 메서드가 제거되었습니다.


OpenerDirector 객체
===================

"OpenerDirector" 인스턴스에는 다음과 같은 메서드가 있습니다:

OpenerDirector.add_handler(handler)

   *handler*는 "BaseHandler"의 인스턴스여야 합니다. 다음 메서드가 검색
   되어, 가능한 체인에 추가됩니다 (HTTP 에러는 특별한 경우임에 유의하
   십시오). 다음에서 *protocol*은 처리할 실제 프로토콜로 바꿔야 합니다
   , 예를 들어 "http_response()"는 HTTP 프로토콜 응답 처리기입니다. 또
   한 *type*은 실제 HTTP 코드로 대체해야 합니다, 예를 들어
   "http_error_404()"는 HTTP 404 에러를 처리합니다.

   * "<protocol>_open()" --- 처리기가 *protocol* URL을 여는 방법을 알
     고 있음을 알립니다.

     자세한 정보는 "BaseHandler.<protocol>_open()"을 참조하십시오.

   * "http_error_<type>()" --- 처리기가 HTTP 에러 코드 *type*을 갖는
     HTTP 에러를 처리하는 방법을 알고 있음을 알립니다.

     자세한 정보는 "BaseHandler.http_error_<nnn>()"을 참조하십시오.

   * "<protocol>_error()" --- 처리기가 ("http"가 아닌) *protocol*의 에
     러를 처리하는 방법을 알고 있음을 알립니다.

   * "<protocol>_request()" --- 처리기가 *protocol* 요청을 전처리(pre-
     process)하는 방법을 알고 있음을 알립니다.

     자세한 정보는 "BaseHandler.<protocol>_request()"를 참조하십시오.

   * "<protocol>_response()" --- 처리기가 *protocol* 응답을 후처리
     (post-process)하는 방법을 알고 있음을 알립니다.

     자세한 정보는 "BaseHandler.<protocol>_response()"를 참조하십시오.

OpenerDirector.open(url, data=None[, timeout])

   주어진 *url*(요청 객체나 문자열일 수 있습니다)을 열고, 선택적으로
   주어진 *data*를 전달합니다. 인자, 반환 값 및 발생하는 예외는
   "urlopen()"과 같습니다 (단순히 현재 설치된 전역 "OpenerDirector"의
   "open()" 메서드를 호출합니다). 선택적 *timeout* 매개 변수는 연결 시
   도와 같은 연산을 블로킹하기 위한 시간제한을 초 단위로 지정합니다 (
   지정하지 않으면 전역 기본 시간제한 설정이 사용됩니다). 시간제한 기
   능은 실제로는 HTTP, HTTPS 및 FTP 연결에서만 작동합니다.

OpenerDirector.error(proto, *args)

   주어진 프로토콜의 에러를 처리합니다. 이것은 주어진 프로토콜에 대해
   등록된 에러 처리기를 주어진 인자(프로토콜 특정입니다)로 호출합니다.
   HTTP 프로토콜은 HTTP 응답 코드를 사용하여 특정 에러 처리기를 결정하
   는 특수한 경우입니다; 처리기 클래스의 "http_error_<type>()" 메서드
   를 참조하십시오.

   반환 값과 발생하는 예외는 "urlopen()"과 같습니다.

OpenerDirector 객체는 다음 3단계로 URL을 엽니다:

각 단계에서 이러한 메서드가 호출되는 순서는 처리기 인스턴스를 정렬하여
결정됩니다.

1. "<protocol>_request()"와 같은 이름의 메서드를 가진 모든 처리기가 요
   청을 전처리하기 위해 해당 메서드가 호출됩니다.

2. "<protocol>_open()"과 같은 이름의 메서드를 가진 처리기가 요청을 처
   리하기 위해 호출됩니다. 이 단계는 처리기가 "None"이 아닌 값(즉, 응
   답)을 반환하거나, 예외(보통 "URLError")를 발생시킬 때 종료됩니다.
   예외 전파가 허용됩니다.

   사실, 위의 알고리즘은 "default_open()"이라는 메서드를 먼저 시도됩니
   다. 이러한 모든 메서드가 "None"을 반환하면, 알고리즘은
   "<protocol>_open()"과 같은 이름의 메서드에 대해 반복합니다. 이러한
   모든 메서드가 "None"을 반환하면, 알고리즘은 "unknown_open()"이라는
   메서드에 대해 반복합니다.

   이러한 메서드의 구현은 부모 "OpenerDirector" 인스턴스의 "open()"과
   "error()" 메서드의 호출을 수반할 수 있음에 유의하십시오.

3. "<protocol>_response()"와 같은 이름의 메서드가 있는 모든 처리기는
   응답을 후처리하기 위해 해당 메서드가 호출됩니다.


BaseHandler 객체
================

"BaseHandler" 객체는 직접적으로 유용한 몇 가지 메서드와 파생 클래스에
서 사용하기 위한 다른 메서드를 제공합니다. 다음은 직접 사용하기 위한
것입니다:

BaseHandler.add_parent(director)

   director를 부모로 추가합니다.

BaseHandler.close()

   모든 부모를 제거합니다.

다음 어트리뷰트와 메서드는 "BaseHandler"에서 파생된 클래스에서만 사용
해야 합니다.

참고:

  "<protocol>_request()"나 "<protocol>_response()" 메서드를 정의하는
  서브 클래스는 "*Processor"라고 이름 붙이는 규칙이 채택되었습니다; 다
  른 모든 것들의 이름은 "*Handler"입니다.

BaseHandler.parent

   다른 프로토콜을 사용하여 열거나 에러를 처리하는 데 사용할 수 있는
   유효한 "OpenerDirector".

BaseHandler.default_open(req)

   이 메서드는 "BaseHandler"에 정의되지 *않았지만*, 서브 클래스가 모든
   URL을 포착하려면 이를 정의해야 합니다.

   구현되면 이 메서드는 부모 "OpenerDirector"에 의해 호출됩니다.
   "OpenerDirector"의 "open()" 메서드의 반환 값에 설명된 대로 파일류
   객체를 반환하거나 "None"을 반환해야 합니다. 진짜 예외적인 상황이 발
   생하지 않는 한  (예를 들어, "MemoryError"는 "URLError"로 매핑하지
   않아야 합니다), "URLError"를 발생해야 합니다.

   이 메서드는 프로토콜별 open 메서드보다 먼저 호출됩니다.

BaseHandler.<protocol>_open(req)

   이 메서드는 "BaseHandler" 에 정의되지 *않았지만*, 서브 클래스가 주
   어진 프로토콜로 URL을 처리하려면 이를 정의해야 합니다.

   정의되면, 이 메서드는 부모 "OpenerDirector"에 의해 호출됩니다. 반환
   값은 "default_open()"과 같아야 합니다.

BaseHandler.unknown_open(req)

   이 메서드는 "BaseHandler" 에 정의되지 *않았지만*, 서브 클래스는 등
   록된 특정 처리기가 없는 모든 URL을 잡아서 열려면 이를 정의해야 합니
   다.

   구현되면, 이 메서드는 "parent" "OpenerDirector"에 의해 호출됩니다.
   반환 값은 "default_open()"과 같아야 합니다.

BaseHandler.http_error_default(req, fp, code, msg, hdrs)

   이 메서드는 "BaseHandler" 에 정의되지 *않았지만*, 서브 클래스는 달
   리 처리되지 않은 HTTP 에러에 대해 포괄적인 처리를 제공하려면 이를
   재정의해야 합니다. 에러가 발생하는 "OpenerDirector"에 의해 자동으로
   호출되며, 다른 상황에서는 일반적으로 호출되지 않아야 합니다.

   "OpenerDirector" will call this method with five positional
   arguments:

   1. a "Request" object,

   2. a file-like object with the HTTP error body,

   3. the three-digit code of the error, as a string,

   4. the user-visible explanation of the code, as a string, and

   5. the headers of the error, as a mapping object.

   반환 값과 발생하는 예외는 "urlopen()"의 것과 같아야 합니다.

BaseHandler.http_error_<nnn>(req, fp, code, msg, hdrs)

   *nnn*은 3자리 HTTP 에러 코드여야 합니다. 이 메서드도 "BaseHandler"
   에 정의되어 있지 않지만, 존재한다면 코드가 *nnn* 인 HTTP 에러가 발
   생할 때 서브 클래스의 인스턴스에 대해 호출됩니다.

   특정 HTTP 에러를 처리하려면 서브 클래스가 이 메서드를 재정의해야 합
   니다.

   인자, 반환 값 및 발생하는 예외는 "http_error_default()"와 같아야 합
   니다.

BaseHandler.<protocol>_request(req)

   이 메서드는 "BaseHandler" 에 정의되지 *않았지만*, 서브 클래스는 주
   어진 프로토콜의 요청을 전처리하려면 이를 정의해야 합니다.

   정의되면, 이 메서드는 부모 상위 "OpenerDirector"에 의해 호출됩니다.
   *req*는 "Request" 객체가 됩니다. 반환 값은 "Request" 객체여야 합니
   다.

BaseHandler.<protocol>_response(req, response)

   이 메서드는 "BaseHandler" 에 정의되지 *않았지만*, 서브 클래스는 주
   어진 프로토콜의 응답을 후처리하려면 이를 정의해야 합니다.

   정의되면, 이 메서드는 부모 "OpenerDirector"에 의해 호출됩니다.
   *req*는 "Request" 객체가 됩니다. *response*는 "urlopen()"의 반환 값
   과 같은 인터페이스를 구현하는 객체가 됩니다. 반환 값은 "urlopen()"
   의 반환 값과 같은 인터페이스를 구현해야 합니다.


HTTPRedirectHandler 객체
========================

참고:

  일부 HTTP 리디렉션은 이 모듈의 클라이언트 코드로부터의 액션을 요구합
  니다. 이 경우, "HTTPError"가 발생합니다. 다양한 리디렉션 코드의 정확
  한 의미에 대한 자세한 내용은 **RFC 2616**을 참조하십시오
  .HTTPRedirectHandler 에 HTTP, HTTPS 또는 FTP URL이 아닌 리디렉션 된
  URL이 제공되면 보안을 고려하여 "HTTPError" 예외가 발생했습니다.

HTTPRedirectHandler.redirect_request(req, fp, code, msg, hdrs, newurl)

   리디렉션에 대한 응답으로 "Request"나 "None"을 반환합니다. 이것은 서
   버로부터 리디렉션이 수신될 때 "http_error_30*()" 메서드의 기본 구현
   에 의해 호출됩니다. 리디렉션이 일어나야 하면, "http_error_30*()"이
   *newurl*로 리디렉션을 수행할 수 있도록 새 "Request"를 반환합니다.
   그렇지 않으면 다른 처리기가 이 URL을 처리하려고 시도하지 않아야 한
   다면 "HTTPError"를 발생시키고, 자신은 할 수 없지만 다른 처리기가 처
   리할 수 있다면 "None"을 반환합니다.

   참고:

     이 메서드의 기본 구현은 **RFC 2616**을 엄격하게 따르지 않습니다.
     즉, "POST" 요청에 대한 301과 302 응답은 사용자의 확인 없이 자동으
     로 리디렉션 되지 않아야 합니다. 실제로는, 브라우저들이 POST를
     "GET"으로 변경하여 이러한 응답의 자동 리디렉션을 허용하며, 기본
     구현은 이 동작을 재현합니다.

HTTPRedirectHandler.http_error_301(req, fp, code, msg, hdrs)

   "Location:"이나 "URI:" URL로 리디렉션 합니다. 이 메서드는 HTTP
   'moved permanently(영구적으로 이전했음)' 응답을 받을 때 부모
   "OpenerDirector"에 의해 호출됩니다.

HTTPRedirectHandler.http_error_302(req, fp, code, msg, hdrs)

   "http_error_301()"과 같지만, 'found(발견됨)' 응답에 대해 호출됩니다
   .

HTTPRedirectHandler.http_error_303(req, fp, code, msg, hdrs)

   "http_error_301()"과 같지만, 'see other(다른 곳을 보세요)' 응답에
   대해 호출됩니다.

HTTPRedirectHandler.http_error_307(req, fp, code, msg, hdrs)

   "http_error_301()"과 같지만, 'temporary redirect(임시 리디렉션)' 응
   답에 대해 호출됩니다. 요청 메서드를 "POST"에서 "GET"으로 바꾸는 것
   을 허락하지 않습니다.

HTTPRedirectHandler.http_error_308(req, fp, code, msg, hdrs)

   "http_error_301()"과 같지만, 'permanent redirect(영구 리디렉션)' 응
   답에 대해 호출됩니다. 요청 메서드를 "POST"에서 "GET"으로 바꾸는 것
   을 허락하지 않습니다.

   Added in version 3.11.


HTTPCookieProcessor 객체
========================

"HTTPCookieProcessor" 인스턴스에는 하나의 어트리뷰트가 있습니다:

HTTPCookieProcessor.cookiejar

   쿠키가 저장되는 "http.cookiejar.CookieJar".


ProxyHandler 객체
=================

ProxyHandler.<protocol>_open(request)

   "ProxyHandler"에는 생성자에 지정된 *proxies* 딕셔너리에 프락시가 있
   는 모든 *protocol*에 대해 "<protocol>_open()" 메서드가 있습니다. 이
   메서드는 "request.set_proxy()"를 호출하여 요청이 프락시를 통과하도
   록 수정하고, 체인에 있는 다음 처리기를 호출하여 실제로 프로토콜을
   실행합니다.


HTTPPasswordMgr 객체
====================

이 메서드는 "HTTPPasswordMgr" 과 "HTTPPasswordMgrWithDefaultRealm" 객
체에서 사용 가능합니다.

HTTPPasswordMgr.add_password(realm, uri, user, passwd)

   *uri*는 단일 URI이거나 URI의 시퀀스일 수 있습니다. *realm*, *user*
   및 *passwd*는 문자열이어야 합니다. 이는 *realm*과 지정된 URI 중 어
   느 하나의 슈퍼 URI에 대한 인증이 주어질 때 "(user, passwd)"가 인증
   토큰으로 사용되도록 합니다.

HTTPPasswordMgr.find_user_password(realm, authuri)

   주어진 realm과 URI에 대한 사용자/암호를 (있다면) 가져옵니다. 일치하
   는 사용자/암호가 없으면 이 메서드는 "(None, None)"을 반환합니다.

   "HTTPPasswordMgrWithDefaultRealm" 객체의 경우, 주어진 *realm*에 일
   치하는 사용자/암호가 없으면 영역 "None"이 검색됩니다.


HTTPPasswordMgrWithPriorAuth 객체
=================================

이 암호 관리자는 "HTTPPasswordMgrWithDefaultRealm"를 확장하여 인증 자
격 증명을 항상 보내야 하는 URI를 추적하는 것을 지원합니다.

HTTPPasswordMgrWithPriorAuth.add_password(realm, uri, user, passwd, is_authenticated=False)

   *realm*, *uri*, *user*, *passwd*는 "HTTPPasswordMgr.add_password()"
   와 같습니다. *is_authenticated*는 주어진 URI나 URI 리스트에 대한
   "is_authenticated" 플래그의 초깃값을 설정합니다. *is_authenticated*
   가 "True"로 지정되면, *realm*는 무시됩니다.

HTTPPasswordMgrWithPriorAuth.find_user_password(realm, authuri)

   "HTTPPasswordMgrWithDefaultRealm" 객체와 같습니다

HTTPPasswordMgrWithPriorAuth.update_authenticated(self, uri, is_authenticated=False)

   주어진 *uri*나 URI 리스트에 대해 "is_authenticated" 플래그를 갱신합
   니다.

HTTPPasswordMgrWithPriorAuth.is_authenticated(self, authuri)

   주어진 URI에 대한 "is_authenticated" 플래그의 현재 상태를 반환합니
   다.


AbstractBasicAuthHandler 객체
=============================

AbstractBasicAuthHandler.http_error_auth_reqed(authreq, host, req, headers)

   사용자/암호 쌍을 가져오고 요청을 다시 시도하여 인증 요청을 처리합니
   다. *authreq*는 영역(realm)에 대한 정보가 요청에 포함된 헤더의 이름
   이어야 하고, *host*는 인증할 URL과 경로를 지정하고, *req*는 (실패한
   ) "Request" 객체여야 하며, *headers*는 에러 헤더여야 합니다.

   *host*는 주체(예를 들어 ""python.org"")거나 주체 구성 요소를 포함하
   는 URL(예를 들어 ""http://python.org/"")입니다. 어느 경우이든, 주체
   는 userinfo 구성 요소를 포함하지 않아야 합니다 (따라서,
   ""python.org""와 ""python.org:80""은 좋지만,
   ""joe:password@python.org""는 유효하지 않습니다).


HTTPBasicAuthHandler 객체
=========================

HTTPBasicAuthHandler.http_error_401(req, fp, code, msg, hdrs)

   가능하다면 인증 정보로 요청을 재시도합니다.


ProxyBasicAuthHandler 객체
==========================

ProxyBasicAuthHandler.http_error_407(req, fp, code, msg, hdrs)

   가능하다면 인증 정보로 요청을 재시도합니다.


AbstractDigestAuthHandler 객체
==============================

AbstractDigestAuthHandler.http_error_auth_reqed(authreq, host, req, headers)

   *authreq*는 영역(realm)에 대한 정보가 요청에 포함된 헤더의 이름이어
   야 하고, *host*는 인증할 호스트여야 하고, *req*는 (실패한)
   "Request" 객체여야 하며, *headers*는 에러 헤더여야 합니다.


HTTPDigestAuthHandler 객체
==========================

HTTPDigestAuthHandler.http_error_401(req, fp, code, msg, hdrs)

   가능하다면 인증 정보로 요청을 재시도합니다.


ProxyDigestAuthHandler 객체
===========================

ProxyDigestAuthHandler.http_error_407(req, fp, code, msg, hdrs)

   가능하다면 인증 정보로 요청을 재시도합니다.


HTTPHandler 객체
================

HTTPHandler.http_open(req)

   Send an HTTP request, which can be either GET or POST, depending on
   "req.data".


HTTPSHandler 객체
=================

HTTPSHandler.https_open(req)

   Send an HTTPS request, which can be either GET or POST, depending
   on "req.data".


FileHandler 객체
================

FileHandler.file_open(req)

   호스트 이름이 없거나, 호스트 이름이 "'localhost'"인 경우 파일을 로
   컬에서 엽니다.

   버전 3.2에서 변경: 이 메서드는 로컬 호스트 명에만 적용할 수 있습니
   다. 원격 호스트 이름이 제공되면, "URLError"가 발생합니다.


DataHandler 객체
================

DataHandler.data_open(req)

   데이터 URL을 읽습니다. 이러한 종류의 URL에는 URL 자체에 인코딩된 콘
   텐츠가 포함됩니다. 데이터 URL 문법은 **RFC 2397**에 지정되어 있습니
   다. 이 구현은 base64로 인코딩된 데이터 URL의 공백을 무시하기 때문에
   URL은 소스 파일과 관계없이 줄 넘김 될 수 있습니다. 그러나 일부 브라
   우저가 base64로 인코딩된 데이터 URL 끝에 패딩이 누락된 것에 대해 신
   경 쓰지 않지만, 이 구현은 이 경우 "ValueError"를 발생시킵니다.


FTPHandler 객체
===============

FTPHandler.ftp_open(req)

   *req*로 표시된 FTP 파일을 엽니다. 로그인은 항상 빈 사용자 이름과 암
   호로 수행됩니다.


CacheFTPHandler 객체
====================

"CacheFTPHandler" 객체는 다음과 같은 추가 메서드가 있는 "FTPHandler"
객체입니다:

CacheFTPHandler.setTimeout(t)

   연결 시간제한을 *t* 초로 설정합니다.

CacheFTPHandler.setMaxConns(m)

   캐시 된 최대 연결 수를 *m*으로 설정합니다.


UnknownHandler 객체
===================

UnknownHandler.unknown_open()

   "URLError" 예외를 발생시킵니다.


HTTPErrorProcessor 객체
=======================

HTTPErrorProcessor.http_response(request, response)

   HTTP 에러 응답을 처리합니다.

   200 에러 코드의 경우, 응답 객체가 즉시 반환됩니다.

   200이 아닌 에러 코드의 경우, "OpenerDirector.error()"를 통해 단순히
   작업을 "http_error_<type>()" 처리기 메서드로 전달합니다. 결국, 다른
   처리기가 에러를 처리하지 않으면 "HTTPDefaultErrorHandler"는
   "HTTPError"를 발생시킵니다.

HTTPErrorProcessor.https_response(request, response)

   HTTPS 에러 응답을 처리합니다.

   동작은 "http_response()"와 같습니다.


예
==

아래 예 외에도 urllib 패키지를 사용하여 인터넷 리소스를 가져오는 방법
에는 더 많은 예가 나와 있습니다.

이 예제는 python.org 메인 페이지를 가져와서 첫 300바이트를 표시합니다:

   >>> import urllib.request
   >>> with urllib.request.urlopen('http://www.python.org/') as f:
   ...     print(f.read(300))
   ...
   b'<!doctype html>\n<!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->\n<!--[if IE 7]>      <html class="no-js ie7 lt-ie8 lt-ie9">          <![endif]-->\n<!--[if IE 8]>      <html class="no-js ie8 lt-ie9">

urlopen은 바이트열 객체를 반환함에 유의하십시오. 이는 urlopen이 HTTP
서버로부터 수신한 바이트 스트림의 인코딩을 자동으로 결정할 방법이 없기
때문입니다. 일반적으로, 프로그램은 일단 적절한 인코딩을 결정하거나 추
측하면 반환된 바이트열 객체를 문자열로 디코딩합니다.

다음 HTML 명세 문서 https://html.spec.whatwg.org/#charset 은 HTML이나
XML 문서가 인코딩 정보를 지정할 수 있는 다양한 방법을 나열합니다.

For additional information, see the W3C document:
https://www.w3.org/International/questions/qa-html-encoding-
declarations.

python.org 웹 사이트는 메타 태그에 지정된 대로 *utf-8* 인코딩을 사용하
므로, 바이트열 객체를 디코딩할 때도 이를 사용합니다:

   >>> with urllib.request.urlopen('http://www.python.org/') as f:
   ...     print(f.read(100).decode('utf-8'))
   ...
   <!doctype html>
   <!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->
   <!-

*컨텍스트 관리자* 방식을 사용하지 않고도 같은 결과를 얻을 수 있습니다:

   >>> import urllib.request
   >>> f = urllib.request.urlopen('http://www.python.org/')
   >>> try:
   ...     print(f.read(100).decode('utf-8'))
   ... finally:
   ...     f.close()
   ...
   <!doctype html>
   <!--[if lt IE 7]>   <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9">   <![endif]-->
   <!--

다음 예에서는, CGI의 표준 입력으로 데이터 스트림을 전송하고 반환되는
데이터를 읽습니다. 이 예제는 파이썬 설치가 SSL을 지원할 때만 작동함에
유의하십시오.

   >>> import urllib.request
   >>> req = urllib.request.Request(url='https://localhost/cgi-bin/test.cgi',
   ...                       data=b'This data is passed to stdin of the CGI')
   >>> with urllib.request.urlopen(req) as f:
   ...     print(f.read().decode('utf-8'))
   ...
   Got Data: "This data is passed to stdin of the CGI"

위 예제에서 사용한 샘플 CGI의 코드는 다음과 같습니다:

   #!/usr/bin/env python
   import sys
   data = sys.stdin.read()
   print('Content-type: text/plain\n\nGot Data: "%s"' % data)

다음은 "Request"를 사용하여 "PUT" 요청을 수행하는 예입니다:

   import urllib.request
   DATA = b'some data'
   req = urllib.request.Request(url='http://localhost:8080', data=DATA, method='PUT')
   with urllib.request.urlopen(req) as f:
       pass
   print(f.status)
   print(f.reason)

기본 HTTP 인증 사용:

   import urllib.request
   # 기본 HTTP 인증을 지원하는 OpenerDirector를 만듭니다...
   auth_handler = urllib.request.HTTPBasicAuthHandler()
   auth_handler.add_password(realm='PDQ Application',
                             uri='https://mahler:8092/site-updates.py',
                             user='klem',
                             passwd='kadidd!ehopper')
   opener = urllib.request.build_opener(auth_handler)
   # ...그리고 urlopen과 함께 사용할 수 있도록 전역으로 설치합니다.
   urllib.request.install_opener(opener)
   with urllib.request.urlopen('http://www.example.com/login.html') as f:
       print(f.read().decode('utf-8'))

"build_opener()"는 기본적으로 "ProxyHandler"를 포함하여 많은 처리기를
제공합니다. 기본적으로, "ProxyHandler"는 "<scheme>_proxy"라는 이름의
환경 변수를 사용합니다, 여기서 "<scheme>"은 관련된 URL 스킴입니다. 예
를 들어, HTTP 프락시의 URL을 얻기 위해 "http_proxy" 환경 변수를 읽습니
다.

이 예는 기본 "ProxyHandler"를 프로그래밍 방식으로 제공되는 프락시 URL
을 사용하는 것으로 대체하고, "ProxyBasicAuthHandler"로 프락시 인증 지
원을 추가합니다.

   proxy_handler = urllib.request.ProxyHandler({'http': 'http://www.example.com:3128/'})
   proxy_auth_handler = urllib.request.ProxyBasicAuthHandler()
   proxy_auth_handler.add_password('realm', 'host', 'username', 'password')

   opener = urllib.request.build_opener(proxy_handler, proxy_auth_handler)
   # 이번에는, OpenerDirector를 설치하지 않고 직접 사용합니다:
   with opener.open('http://www.example.com/login.html') as f:
      print(f.read().decode('utf-8'))

HTTP 헤더 추가하기:

"Request" 생성자에 *headers* 인자를 사용하십시오, 또는:

   import urllib.request
   req = urllib.request.Request('http://www.example.com/')
   req.add_header('Referer', 'http://www.python.org/')
   # Customize the default User-Agent header value:
   req.add_header('User-Agent', 'urllib-example/0.1 (Contact: . . .)')
   with urllib.request.urlopen(req) as f:
       print(f.read().decode('utf-8'))

"OpenerDirector"는 모든 "Request"에 *User-Agent* 헤더를 자동으로 추가
합니다. 이것을 바꾸려면:

   import urllib.request
   opener = urllib.request.build_opener()
   opener.addheaders = [('User-agent', 'Mozilla/5.0')]
   with opener.open('http://www.example.com/') as f:
      print(f.read().decode('utf-8'))

또한, "Request"가 "urlopen()"(또는 "OpenerDirector.open()")으로 전달될
때 몇 가지 표준 헤더(*Content-Length*, *Content-Type* 및 *Host*)가 추
가됨을 기억하십시오.

다음은 "GET" 메서드를 사용하여 파라미터가 포함된 URL을 가져오는 예제
세션입니다:

   >>> import urllib.request
   >>> import urllib.parse
   >>> params = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
   >>> url = "http://www.musi-cal.com/cgi-bin/query?%s" % params
   >>> with urllib.request.urlopen(url) as f:
   ...     print(f.read().decode('utf-8'))
   ...

다음 예제는 대신 "POST" 메서드를 사용합니다. urlencode의 파라미터 출력
이 데이터로 urlopen에 보내기 전에 바이트열로 인코딩됨에 유의하십시오:

   >>> import urllib.request
   >>> import urllib.parse
   >>> data = urllib.parse.urlencode({'spam': 1, 'eggs': 2, 'bacon': 0})
   >>> data = data.encode('ascii')
   >>> with urllib.request.urlopen("http://requestb.in/xrbl82xr", data) as f:
   ...     print(f.read().decode('utf-8'))
   ...

다음 예제는 명시적으로 지정된 HTTP 프락시를 사용하여 환경 설정을 대체
합니다:

   >>> import urllib.request
   >>> proxies = {'http': 'http://proxy.example.com:8080/'}
   >>> opener = urllib.request.build_opener(urllib.request.ProxyHandler(proxies))
   >>> with opener.open("http://www.python.org") as f:
   ...     f.read().decode('utf-8')
   ...

다음 예제는 프락시를 전혀 사용하지 않도록 환경 설정을 대체합니다:

   >>> import urllib.request
   >>> opener = urllib.request.build_opener(urllib.request.ProxyHandler({}}))
   >>> with opener.open("http://www.python.org/") as f:
   ...     f.read().decode('utf-8')
   ...


레거시 인터페이스
=================

다음 함수와 클래스는 파이썬 2 모듈 "urllib"("urllib2"가 아니라)에서 이
식됩니다. 나중에 언젠가 폐지될 수 있습니다.

urllib.request.urlretrieve(url, filename=None, reporthook=None, data=None)

   URL로 표시된 네트워크 객체를 로컬 파일로 복사합니다. URL이 로컬 파
   일을 가리키면, 파일 이름을 제공하지 않는 한 객체가 복사되지 않습니
   다. 튜플 "(filename, headers)"를 반환합니다. 여기서 *filename*은 객
   체를 찾을 수 있는 로컬 파일 이름이며, *headers*는 (원격 객체에 대해
   ) "urlopen()"이 반환한 객체의 "info()" 메서드가 반환한 것입니다. 예
   외는 "urlopen()"과 같습니다.

   있다면, 두 번째 인자는 복사할 파일 위치를 지정합니다 (없으면, 위치
   는 생성된 이름을 가진 임시 파일이 됩니다). 있다면, 세 번째 인자는
   네트워크 연결이 이루어질 때 한 번 호출되고 그 이후에 각 블록을 읽을
   때마다 한 번씩 호출되는 콜러블입니다. 콜러블에는 세 개의 인자가 전
   달됩니다; 지금까지 전송된 블록 수, 바이트 단위의 블록 크기 및 파일
   의 전체 크기. 세 번째 인자는 가져오기 요청에 대한 응답으로 파일 크
   기를 반환하지 않는 구형 FTP 서버에서 "-1"일 수 있습니다.

   다음 예는 가장 일반적인 사용 시나리오를 보여줍니다:

      >>> import urllib.request
      >>> local_filename, headers = urllib.request.urlretrieve('http://python.org/')
      >>> html = open(local_filename)
      >>> html.close()

   *url*이 "http:" 스킴 식별자를 사용하면, "POST" 요청을 지정하기 위해
   선택적 *data* 인자가 제공될 수 있습니다 (일반적으로 요청형은 "GET"
   입니다). *data* 인자는 표준 *application/x-www-form-urlencoded* 형
   식의 바이트열 객체여야 합니다; "urllib.parse.urlencode()" 함수를 참
   조하십시오.

   "urlretrieve()"는 사용 가능한 데이터양이 예상 양(*Content-Length*
   헤더에 의해 보고된 크기)보다 작은 것을 감지하면
   "ContentTooShortError"를 발생시킵니다. 예를 들어, 다운로드가 중단된
   경우에 발생할 수 있습니다.

   *Content-Length*는 하한값으로 취급됩니다: 읽을 데이터가 더 있으면,
   urlretrieve는 더 많은 데이터를 읽지만, 사용 가능한 데이터가 부족하
   면 예외가 발생합니다.

   이 경우에도 다운로드된 데이터를 여전히 가져올 수 있으며, 예외 인스
   턴스의 "content" 어트리뷰트에 저장됩니다.

   *Content-Length* 헤더가 제공되지 않으면, urlretrieve는 다운로드 한
   데이터의 크기를 확인할 수 없고, 그냥 반환합니다. 이 경우 다운로드가
   성공했다고 가정해야 합니다.

urllib.request.urlcleanup()

   "urlretrieve()"에 대한 이전 호출로 남겨졌을 수 있는 임시 파일을 정
   리합니다.


"urllib.request" 제약 사항
==========================

* 현재, 다음과 같은 프로토콜만 지원됩니다: HTTP (버전 0.9와 1.0), FTP,
  로컬 파일 및 데이터 URL.

  버전 3.4에서 변경: 데이터 URL에 대한 지원이 추가되었습니다.

* "urlretrieve()"의 캐싱 기능은 누군가가 만료 시간 헤더의 적절한 처리
  를 해킹할 시간을 찾을 때까지 비활성화되었습니다.

* 특정 URL이 캐시에 있는지를 조회하는 함수가 있어야 합니다.

* 이전 버전과의 호환성을 위해, URL이 로컬 파일을 가리키는 것으로 보이
  지만 파일을 열 수 없으면, FTP 프로토콜을 사용하여 URL을 다시 해석합
  니다. 이로 인해 때때로 혼란스러운 에러 메시지가 발생할 수 있습니다.

* "urlopen()"과 "urlretrieve()" 함수는 네트워크 연결이 이루어지기를 기
  다리는 동안 임의의 긴 지연을 유발할 수 있습니다. 이는 스레드를 사용
  하지 않고 이러한 함수를 사용하여 대화식 웹 클라이언트를 구축하기 어
  렵다는 것을 뜻합니다.

* "urlopen()"이나 "urlretrieve()"가 반환한 데이터는 서버가 반환한 원시
  데이터입니다. 바이너리 데이터 (가령 이미지), 평문 텍스트 또는 (예를
  들어) HTML일 수 있습니다. HTTP 프로토콜은 응답 헤더에 유형 정보를 제
  공하는데, *Content-Type* 헤더를 통해 검사할 수 있습니다. 반환된 데이
  터가 HTML이면, "html.parser" 모듈을 사용하여 구문 분석할 수 있습니다
  .

* The code handling the FTP protocol cannot differentiate between a
  file and a directory.  This can lead to unexpected behavior when
  attempting to read a URL that points to a file that is not
  accessible.  If the URL ends in a "/", it is assumed to refer to a
  directory and will be handled accordingly.  But if an attempt to
  read a file leads to a 550 error (meaning the URL cannot be found or
  is not accessible, often for permission reasons), then the path is
  treated as a directory in order to handle the case when a directory
  is specified by a URL but the trailing "/" has been left off.  This
  can cause misleading results when you try to fetch a file whose read
  permissions make it inaccessible; the FTP code will try to read it,
  fail with a 550 error, and then perform a directory listing for the
  unreadable file. If fine-grained control is needed, consider using
  the "ftplib" module.


"urllib.response" --- urllib가 사용하는 응답 클래스
***************************************************

"urllib.response" 모듈은 "read()"와 "readline()"을 포함하여 최소한의
파일류 인터페이스를 정의하는 함수와 클래스를 정의합니다. 이 모듈에 의
해 정의된 함수는 "urllib.request" 모듈에 의해 내부적으로 사용됩니다.
일반적인 응답 객체는 "urllib.response.addinfourl" 인스턴스입니다:

class urllib.response.addinfourl

   url

      가져온 자원의 URL, 일반적으로 리디렉션을 따라갔는지 판별하는 데
      사용됩니다.

   headers

      "EmailMessage" 인스턴스 형식으로 응답의 헤더를 반환합니다.

   status

      Added in version 3.9.

      서버가 반환한 상태 코드.

   geturl()

      버전 3.9부터 폐지됨: 폐지되었고 "url"로 대체되었습니다.

   info()

      버전 3.9부터 폐지됨: 폐지되었고 "headers"로 대체되었습니다.

   code

      버전 3.9부터 폐지됨: 폐지되었고 "status"로 대체되었습니다.

   getcode()

      버전 3.9부터 폐지됨: 폐지되었고 "status"로 대체되었습니다.
