"urllib.request" --- Biblioteca extensible para abrir URLs
**********************************************************

**Código fuente:** Lib/urllib/request.py

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

El módulo "urllib.request" define funciones y clases que ayudan en la
apertura de URLs (la mayoría HTTP) en un mundo complejo ---
autenticación básica y digest, redirecciones, cookies y más.

Ver también:

  Se recomienda el paquete Requests para una interfaz de cliente HTTP
  de mayor nivel.

Advertencia:

  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"] = "*"").

Availability: not Emscripten, not WASI.

Este módulo no funciona o no está disponible en las plataformas
WebAssembly "wasm32-emscripten" y "wasm32-wasi". Consulte Plataformas
WebAssembly para obtener más información.

El módulo "urllib.request" define las siguientes funciones:

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

   Open *url*, which can be either a string containing a valid,
   properly encoded URL, or a "Request" object.

   *data* debe ser un objeto que especifique datos adicionales a ser
   enviados al servidor o "None" si no se necesitan tales datos. Vea
   "Request" para más detalles.

   el módulo urllib.request usa HTTP/1.1 e incluye el encabezado
   "Connection:close" en sus peticiones HTTP.

   El parámetro opcional *timeout* especifica un tiempo de expiración
   en segundos para operaciones bloqueantes como el intento de
   conexión (si no se especifica, será usado el tiempo de expiración
   global predeterminado). Esto actualmente sólo funciona para
   conexiones HTTP, HTTPS y FTP.

   Si se especifica *context*, debe ser una instancia "ssl.SSLContext"
   describiendo las diferentes opciones SSL. Vea "HTTPSConnection"
   para más detalles.

   Los parámetros opcionales *cafile* y *capath* especifican un
   conjunto de certificados CA de confianza para peticiones HTTPS.
   *cafile* debe apuntar a un único archivo que contenga un paquete de
   certificados CA, mientras *capath* debe apuntar a un directorio de
   archivos de certificado hash. Se puede encontrar más información en
   "ssl.SSLContext.load_verify_locations()".

   Se ignora el parámetro *cadefault*.

   Esta función siempre retorna un objeto que puede actuar como un
   *gestor de contexto*, y tiene las propiedades *url*, *headers* y
   *status*. Véase "urllib.response.addinfourl" para más detalles
   sobre estas propiedades.

   Para URLs HTTP y HTTPS, esta función retorna un objeto
   "http.client.HTTPResponse" ligeramente modificado. Adicionalmente a
   los tres nuevos métodos anteriores, el atributo msg contiene la
   misma información que el atributo "reason" --- la frase de motivo
   devuelta por el servidor --- en lugar de los encabezados de la
   respuesta como se especifica en la documentación para
   "HTTPResponse".

   Para URLs FTP, de archivo y de datos y para peticiones manejadas
   explícitamente por las clases heredadas "URLopener" y
   "FancyURLopener", esta función retorna un objeto
   "urllib.response.addinfourl".

   Genera "URLError" en errores de protocolo.

   Tenga en cuenta que "None" puede ser retornado si ningún manejador
   gestiona la petición (aunque el "OpenerDirector" global instalado
   de manera predeterminada usa "UnknownHandler" para asegurar que
   esto nunca suceda).

   In addition, if proxy settings are detected (for example, when a
   "*_proxy" environment variable like "http_proxy" is set),
   "ProxyHandler" is default installed and makes sure the requests are
   handled through the proxy.

   La función heredada de Python 2.6 y anteriores "urllib.urlopen" ha
   sido descontinuada, "urllib.request.urlopen()" corresponde a la
   antigua "urllib2.urlopen". La gestión de proxy, la cual se hacía
   pasando un parámetro diccionario a "urllib.urlopen", puede ser
   obtenida usando objetos "ProxyHandler".

   Genera un evento de auditoría "urllib.Request" con los argumentos
   "fullurl", "data", "headers", "method".

   Distinto en la versión 3.2: *cafile* y *capath* fueron
   añadidos.HTTPS virtual hosts are now supported if possible (that
   is, if "ssl.HAS_SNI" is true).*data* puede ser un objeto iterable.

   Distinto en la versión 3.3: *cadefault* fue añadido.

   Distinto en la versión 3.4.3: *context* fue añadido.

   Distinto en la versión 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()".

   Obsoleto desde la versión 3.6: *cafile*, *capath* y *cadefault*
   están obsoletos en favor de *context*. Por favor, use
   "ssl.SSLContext.load_cert_chain()" en su lugar o deja a
   "ssl.create_default_context()" seleccionar el certificado de
   confianza CA del sistema por ti.

urllib.request.install_opener(opener)

   Instala una instancia "OpenerDirector" como el abridor global
   predeterminado. Instalar un abridor sólo es necesario si quieres
   que urlopen use ese abridor; si no, simplemente invoca
   "OpenerDirector.open()" en lugar de "urlopen()". El código no
   comprueba por un "OpenerDirector" real y cualquier clase con la
   interfaz apropiada funcionará.

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

   Retorna una instancia "OpenerDirector", la cual encadena los
   manejadores en el orden dado. *handler*s pueden ser tanto
   instancias de "BaseHandler" o subclases de "BaseHandler" (en cuyo
   caso debe ser posible invocar el constructor sin ningún parámetro).
   Instancias de las siguientes clases estarán delante del *handler*s,
   a no ser que el *handler*s las contenga, instancias o subclases de
   ellas: "ProxyHandler" (si son detectadas configuraciones de proxy),
   "UnknownHandler", "HTTPHandler", "HTTPDefaultErrorHandler",
   "HTTPRedirectHandler", "FTPHandler", "FileHandler",
   "HTTPErrorProcessor".

   Si la instalación de Python tiene soporte SSL (ej. si se puede
   importar el módulo "ssl"), también será añadida "HTTPSHandler".

   Una subclase de "BaseHandler" puede cambiar también su atributo
   "handler_order" para modificar su posición en la lista de
   manejadores.

urllib.request.pathname2url(path)

   Convierte el nombre de ruta *path* desde la sintaxis local para una
   ruta a la forma usada en el componente ruta de una URL. Esto no
   produce una URL completa. El valor retornado ya estará
   entrecomillado usando la función "quote()".

urllib.request.url2pathname(path)

   Convierte el componente ruta *path* desde una URL codificada con
   porcentajes a la sintaxis local para una ruta. No acepta una URL
   completa. Esta función usa "unquote()" para decodificar *path*.

urllib.request.getproxies()

   Esta función auxiliar retorna un diccionario de esquema para las
   asignaciones de URL del servidor proxy. Escanea el entorno en busca
   de variables denominadas "<scheme>_proxy", tomando en cuenta
   diferencia entre mayúsculas y minúsculas, para todos los sistemas
   operativos primero, y cuando no pueden encontrarla, buscan
   información proxy desde la Configuración del Sistema de macOS y
   desde Registros del Sistema para Windows. Si existen variables de
   entorno tanto en mayúsculas como en minúsculas (y no concuerdan),
   las minúsculas son preferidas.

   Nota:

     Si la variable del entorno "REQUEST_METHOD" está definida, lo
     cual usualmente indica que tu script está ejecutándose en un
     entorno CGI, la variable de entorno "HTTP_PROXY" (mayúsculas
     "_PROXY") será ignorada. Esto es porque esa variable puede ser
     inyectada por un cliente usando el encabezado HTTP "Proxy:". Si
     necesitas usar un proxy HTTP en un entorno CGI, usa
     "ProxyHandler" explícitamente o asegúrate de que el nombre de la
     variable está en minúsculas (o al menos el sufijo "_proxy").

Se proveen las siguientes clases:

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

   Esta clase es un abstracción de una petición URL.

   *url* should be a string containing a valid, properly encoded URL.

   *data* debe ser un objeto que especifique datos adicionales a
   enviar al servidor o "None" si no se necesitan tales datos.
   Actualmente las peticiones HTTP son las únicas que usan *data*. Los
   tipos de objetos soportados incluyen bytes, objetos como archivos e
   iterables de objetos como bytes. Si no se ha provisto el campo de
   encabezado "Content-Length" ni "Transfer-Encoding", "HTTPHandler"
   establecerá estos encabezados de acuerdo al tipo de *data*.
   "Content-Length" será usado para enviar objetos de bytes, mientras
   "Transfer-Encoding: chunked" como se especifica en **RFC 7230**,
   Sección 3.3.1 será usado para enviar archivos y otros iterables.

   Para un método de una petición HTTP POST, *data* debe ser un buffer
   en el formato estándar *application/x-www-form-urlencoded*. La
   función "urllib.parse.urlencode()" toma un mapeo o una secuencia de
   tuplas de dos valores y retorna una cadena de caracteres ASCII en
   este formato. Debe ser codificada a bytes antes de ser usada como
   el parámetro *data*.

   *headers* debe ser un diccionario, y será tratado como si
   "add_header()" fuera invocado con cada clave y valor como
   argumentos. Esto es usado frecuentemente para "parodiar" el valor
   de encabezado "User-Agent", el cual es usado por un navegador para
   identificarse a sí mismo -- algunos servidores HTTP sólo permiten
   peticiones que vienen de navegadores comunes a diferencia de los
   scripts. Por ejemplo, Mozilla Firefox puede identificarse a sí
   mismo como ""Mozilla/5.0 (X11; U; Linux i686) Gecko/20071127
   Firefox/2.0.0.11"", mientras el agente de usuario predeterminado de
   "urllib" es ""Python-urllib/2.6"" (en Python 2.6). Todas las claves
   de los encabezados se envían en camel case.

   Un encabezado apropiado "Content-Type" debe ser incluido si el
   argumento *data* está presente. Si este encabezado no ha sido
   provisto y *data* no es None, será añadido "Content-Type:
   application/x-www-form-urlencoded" de forma predeterminada.

   Los siguientes dos argumentos sólo tienen interés para la gestión
   correcta de cookies HTTP de terceros:

   *origin_req_host* debe ser el host de la petición de la transacción
   origen, como define **RFC 2965**. Por defecto es
   "http.cookiejar.request_host(self)". Este es el nombre de host o la
   dirección IP de la petición original que fue iniciada por el
   usuario. Por ejemplo, si la petición es para una imagen en un
   documento HTML, debe ser el host de la petición para la página que
   contiene la imagen.

   *unverifiable* debe indicar si la petición no es verificable, como
   define **RFC 2965**. Por defecto es "False". Una petición no
   verificable es una cuya URL el usuario no tuvo opción de aprobar.
   Por ejemplo, si la petición es por una imagen en un documento HTML
   y el usuario no tuvo opción de aprobar la obtención automática de
   la imagen, este debe ser verdadero.

   *method* debe ser una cadena que indica el método de la petición
   HTTP que será usado (ej. "'HEAD'"). Si se provee, su valor es
   almacenado en el atributo "method" y usado por "get_method()". Por
   defecto es "'GET'" si *data* es "None", o "'POST'" si no. Las
   subclases pueden indicar un método predeterminado diferente
   estableciendo el atributo "method" es la clase misma.

   Nota:

     La petición no funcionará como se espera si el objeto de datos es
     incapaz de entregar su contenido más de una vez (ej. un archivo o
     un iterable que puede producir el contenido sólo una vez) y la
     petición se reintentará para redirecciones HTTP o autenticación.
     El *data* es enviado al servidor HTTP directamente después de los
     encabezados. No hay soporte para una expectativa de
     funcionamiento 100% continuo en la biblioteca.

   Distinto en la versión 3.3: El argumento "Request.method" es
   añadido a la clase Request.

   Distinto en la versión 3.4: El atributo predeterminado
   "Request.method" puede ser indicado a nivel de clase.

   Distinto en la versión 3.6: No se genera un error si el "Content-
   Length" no ha sido provisto y *data* no es "None" ni un objeto de
   bytes. En su lugar recurre a la codificación de transferencia
   fragmentada.

class urllib.request.OpenerDirector

   La clase "OpenerDirector" abre URLs mediante la encadenación
   conjunta de "BaseHandler". Este maneja el encadenamiento de
   manejadores y la recuperación de errores.

class urllib.request.BaseHandler

   Esta es la clase base para todos los manejadores registrados --- y
   manejan sólo las mecánicas simples del registro.

class urllib.request.HTTPDefaultErrorHandler

   Una clase la cual define un manejador predeterminado para los
   errores de respuesta HTTP; todas las respuestas son convertidas en
   excepciones "HTTPError".

class urllib.request.HTTPRedirectHandler

   Una clase para manejar redirecciones.

class urllib.request.HTTPCookieProcessor(cookiejar=None)

   Una clase para manejar Cookies HTTP.

class urllib.request.ProxyHandler(proxies=None)

   Causa que las peticiones vayan a través de un proxy. Si se provee
   *proxies*, debe ser un diccionario mapeando nombres de protocolos a
   URLs de proxies. Por defecto lee la lista de proxies de las
   variables de entorno "<protocol>_proxy". Si no se establecen
   variables de entorno de proxy, entonces se obtienen las
   configuraciones de proxy en un entorno Windows desde la sección del
   registro de Configuraciones de Internet y en un entorno macOS se
   obtiene la información de proxy desde el Framework de Configuración
   del Sistema.

   Para deshabilitar la detección automática de proxy pasa un
   diccionario vacío.

   La variable de entorno "no_proxy" puede ser usada para especificar
   hosts los cuales no deben ser alcanzados mediante proxy; si se
   establece, debe ser una lista separada por comas de sufijos de
   nombres de host, con ":port" añadidos opcionalmente, por ejemplo
   "cern.ch,ncsa.uiuc.edu,some.host:8080".

   Nota:

     "HTTP_PROXY" será ignorado si se establece una variable
     "REQUEST_METHOD"; vea la documentación de "getproxies()".

class urllib.request.HTTPPasswordMgr

   Mantiene una base de datos de mapeos "(realm, uri) -> (user,
   password)".

class urllib.request.HTTPPasswordMgrWithDefaultRealm

   Mantiene una base de datos de mapeos "(realm, uri) -> (user,
   password)". Un reino de "None" se considera un reino caza todo, el
   cual es buscado si ningún otro reino encaja.

class urllib.request.HTTPPasswordMgrWithPriorAuth

   Una variante de "HTTPPasswordMgrWithDefaultRealm" que también tiene
   una base de datos de mapeos "uri -> is_authenticated". Puede ser
   usada por un manejador BasicAuth para determinar cuando enviar
   credenciales de autenticación inmediatamente en lugar de esperar
   primero a una respuesta "401".

   Nuevo en la versión 3.5.

class urllib.request.AbstractBasicAuthHandler(password_mgr=None)

   Esta es una clase mixin que ayuda con la autenticación HTTP, tanto
   al host remoto y a un proxy. Si se proporciona *password_mgr*, debe
   ser algo compatible con "HTTPPasswordMgr"; refiera a la sección
   Objetos HTTPPasswordMgr para información sobre la interfaz que debe
   ser soportada. Si *passwd_mgr* proporciona también métodos
   "is_authenticated" y "update_authenticated" (vea Objetos
   HTTPPasswordMgrWithPriorAuth), entonces el manejador usará el
   "is_authenticated" resultado para una URI dada para determinar el
   envío o no de credenciales de autenticación con la petición. Si
   "is_authenticated" retorna "True" para la URI, las peticiones
   subsecuentes a la URI o cualquiera de las super URIs incluirán
   automáticamente los credenciales de autenticación.

   Nuevo en la versión 3.5: Añadido soporte "is_authenticated".

class urllib.request.HTTPBasicAuthHandler(password_mgr=None)

   Administra autenticación con el host remoto. Si se proporciona
   *password_mgr*, debe ser compatible con "HTTPPasswordMgr"; refiera
   a la sección Objetos HTTPPasswordMgr para información sobre la
   interfaz que debe ser soportada. HTTPBasicAuthHandler lanzará un
   "ValueError" cuando se presente con un esquema de Autenticación
   incorrecto.

class urllib.request.ProxyBasicAuthHandler(password_mgr=None)

   Administra autenticación con el proxy. Si se proporciona
   *password_mgr* debe ser compatible con "HTTPPasswordMgr"; refiera a
   la sección Objetos HTTPPasswordMgr para información sobre la
   interfaz que debe ser soportada.

class urllib.request.AbstractDigestAuthHandler(password_mgr=None)

   Esto es una clase mixin que ayuda con la autenticación HTTP, tanto
   al host remoto como a un proxy. Si se proporciona *password_mgr*
   debe ser compatible con "HTTPPasswordMgr"; refiera a la sección
   Objetos HTTPPasswordMgr para información sobre la interfaz que debe
   ser soportada.

class urllib.request.HTTPDigestAuthHandler(password_mgr=None)

   Maneja autenticación con el host remoto. Si se proporciona
   *password_mgr* debe ser compatible con "HTTPPasswordMgr"; refiera a
   la sección Objetos HTTPPasswordMgr para información sobre la
   interfaz que debe ser soportada. Cuando se añaden tanto el
   Manejador de Autenticación Digest (*Digest Authentication Handler*)
   como el Manejador de Autenticación Básico (*Basic Authentication
   Handler*) la Autenticación Digest siempre se intenta primero. Si la
   Autenticación Digest retorna una respuesta 40x de nuevo, se envía
   al controlador de Autenticación Básica para Manejar. Este método
   Handler lanzará un "ValueError" cuando sea presentado con un
   esquema de autenticación diferente a Digest o Básico.

   Distinto en la versión 3.3: Genera "ValueError" en Esquema de
   Autenticación no soportado.

class urllib.request.ProxyDigestAuthHandler(password_mgr=None)

   Administra autenticación con el proxy. Si se proporciona
   *password_mgr* debe ser compatible con "HTTPPasswordMgr"; refiera a
   la sección Objetos HTTPPasswordMgr para información sobre la
   interfaz que debe ser soportada.

class urllib.request.HTTPHandler

   Una clase para gestionar apertura de URLs HTTP.

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

   Una clase para gestionar apertura de URLs HTTPS. *context* y
   *check_hostname* tienen el mismo significado que en
   "http.client.HTTPSConnection".

   Distinto en la versión 3.2: *context* y *check_hostname* fueron
   añadidos.

class urllib.request.FileHandler

   Abre archivos locales.

class urllib.request.DataHandler

   Abre URLs de datos.

   Nuevo en la versión 3.4.

class urllib.request.FTPHandler

   Abre URLs FTP.

class urllib.request.CacheFTPHandler

   Abre URLs FTP, manteniendo una caché de conexiones FTP abiertas
   para minimizar retrasos.

class urllib.request.UnknownHandler

   Una clase caza todo para gestionar URLs desconocidas.

class urllib.request.HTTPErrorProcessor

   Procesa errores de respuestas HTTP.


Objetos Request
===============

Los siguientes métodos describen la interfaz pública de "Request" por
lo que pueden ser sobrescritos en subclases. También define varios
atributos públicos que pueden ser usado por clientes para inspeccionar
la respuesta analizada.

Request.full_url

   La URL original pasada al constructor.

   Distinto en la versión 3.4.

   Request.full_url es una propiedad con setter, getter y deleter.
   Obtener "full_url" retorna la petición URL original con el
   fragmento, si este estaba presente.

Request.type

   El esquema de URI.

Request.host

   La autoridad de URI, típicamente un host, pero también puede
   contener un puerto separado por un caracter de doble punto.

Request.origin_req_host

   El host original de la petición, sin puerto.

Request.selector

   La ruta de URI. Si "Request" usa un proxy, entonces selector será
   la URL completa que se pasa al proxy.

Request.data

   El cuerpo de la entidad para la solicitud o "None" si no es
   especificado.

   Distinto en la versión 3.4: Cambiar el valor de "Request.data"
   elimina ahora el encabezado "Content-Length" si fue establecido o
   calculado previamente.

Request.unverifiable

   booleano, indica si la petición no es verificable como se define
   por **RFC 2965**.

Request.method

   El método de petición HTTP a usar. Por defecto su valor es "None",
   lo que significa que "get_method()" realizará su cálculo normal del
   método a usar. Su valor puede ser definido (sobrescribiendo así el
   cálculo predeterminado en "get_method()") tanto proporcionando un
   valor por defecto estableciéndolo a nivel de clase en una subclase
   de "Request" o pasando un valor al constructor de "Request" por
   medio del argumento *method*.

   Nuevo en la versión 3.3.

   Distinto en la versión 3.4: Un valor predeterminado puede ser
   establecido ahora en subclases; previamente sólo podía ser definido
   mediante el argumento del constructor.

Request.get_method()

   Retorna una cadena indicando el método de petición HTTP. Si
   "Request.method" no es "None", retorna su valor, de otra forma
   retorna "'GET'" si "Request.data" es "None" o "'POST'" si no lo es.
   Esto sólo es significativo para peticiones HTTP.

   Distinto en la versión 3.3: get_method ahora mira el valor de
   "Request.method".

Request.add_header(key, val)

   Añade otro encabezado a la petición. Los encabezados actualmente
   son ignorados por todos los manejadores excepto los manejadores
   HTTP, donde son añadidos a la lista de encabezados enviados al
   servidor. Tenga en cuenta que no puede haber más de un encabezado
   con el mismo nombre y las invocaciones posteriores sobrescribirán
   las invocaciones previas en caso de que *key* colisione.
   Actualmente, esto no es una pérdida de funcionalidad HTTP, ya que
   todos los encabezados que tienen sentido cuando son usados más de
   una vez tienen una manera (específica de encabezado) de ganar la
   misma funcionalidad usando sólo un encabezado. Tenga en cuenta que
   los encabezados agregados con este método también se agregan a las
   solicitudes redirigidas.

Request.add_unredirected_header(key, header)

   Añade un encabezado que no será añadido a una petición
   redireccionada.

Request.has_header(header)

   Retorna si la instancia tiene el encabezado nombrado (comprueba
   tanto regular como no redirigido).

Request.remove_header(header)

   Elimina el encabezado nombrado de la instancia de la petición
   (desde encabezados regulares y no redireccionados).

   Nuevo en la versión 3.4.

Request.get_full_url()

   Retorna la URL dada en el constructor.

   Distinto en la versión 3.4.

   Retorna "Request.full_url"

Request.set_proxy(host, type)

   Prepara la petición conectando a un servidor proxy. Los *host* y
   *type* reemplazarán aquellos de la instancia y el selector de la
   instancia será la URL original dada en el constructor.

Request.get_header(header_name, default=None)

   Retorna el valor del encabezado dado.

Request.header_items()

   Retorna una lista de tuplas (header_name, header_value) de los
   encabezados de la Petición.

Distinto en la versión 3.4: Los métodos de petición add_data,
has_data, get_data, get_type, get_host, get_selector,
get_origin_req_host y is_unverifiable que quedaron obsoletos desde 3.3
han sido eliminados.


Objetos OpenerDirector
======================

Las instancias de "OpenerDirector" tienen los siguientes métodos:

OpenerDirector.add_handler(handler)

   *handler* debe ser una instancia de "BaseHandler". Los siguientes
   métodos son buscados y añadidos a las cadenas posibles (tenga en
   cuenta que los errores HTTP son un caso espacial). Tenga en cuenta
   que, en los siguientes, *protocol* debe ser remplazado con el
   protocolo actual a manejar, por ejemplo "http_response()" sería el
   protocolo HTTP del manejador de respuesta. También *type* debe ser
   remplazado con el código HTTP actual, por ejemplo
   "http_error_404()" manejaría errores HTTP 404.

   * "<protocol>_open()" --- signal that the handler knows how to open
     *protocol* URLs.

     Vea "BaseHandler.<protocol>_open()" para más información.

   * "http_error_<type>()" --- signal that the handler knows how to
     handle HTTP errors with HTTP error code *type*.

     Vea "BaseHandler.http_error_<nnn>()" para más información.

   * "<protocol>_error()" --- signal that the handler knows how to
     handle errors from (non-"http") *protocol*.

   * "<protocol>_request()" --- signal that the handler knows how to
     pre-process *protocol* requests.

     Vea "BaseHandler.<protocol>_request()" para más información.

   * "<protocol>_response()" --- signal that the handler knows how to
     post-process *protocol* responses.

     Vea "BaseHandler.<protocol>_response()" para más información.

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

   Abre la *url* dada (la cual puede ser un objeto de petición o una
   cadena de caracteres), pasando opcionalmente el *data* dado. Los
   argumentos, los valores de retorno y las excepciones generadas son
   las mismas que aquellas de "urlopen()" (las cuales simplemente
   invocan el método "open()" en el "OpenerDirector" instalado
   global). El parámetro opcional *timeout* especifica un tiempo de
   expiración en segundos para operaciones bloqueantes como el intento
   de conexión (si no se especifica, el tiempo de expiración global
   será usado). La característica de tiempo de expiración actualmente
   funciona sólo para conexiones HTTP, HTTPS y FTP.

OpenerDirector.error(proto, *args)

   Handle an error of the given protocol.  This will call the
   registered error handlers for the given protocol with the given
   arguments (which are protocol specific).  The HTTP protocol is a
   special case which uses the HTTP response code to determine the
   specific error handler; refer to the "http_error_<type>()" methods
   of the handler classes.

   Retorna si los valores y excepciones generadas son las mismas que
   aquellas de "urlopen()".

Los objetos OpenerDirector abren URLs en tres etapas:

El orden en el cual esos métodos son invocados dentro de cada etapa es
determinado ordenando las instancias manejadoras.

1. Every handler with a method named like "<protocol>_request()" has
   that method called to pre-process the request.

2. Handlers with a method named like "<protocol>_open()" are called to
   handle the request. This stage ends when a handler either returns a
   non-"None" value (ie. a response), or raises an exception (usually
   "URLError").  Exceptions are allowed to propagate.

   In fact, the above algorithm is first tried for methods named
   "default_open()".  If all such methods return "None", the algorithm
   is repeated for methods named like "<protocol>_open()".  If all
   such methods return "None", the algorithm is repeated for methods
   named "unknown_open()".

   Tenga en cuenta que la implementación de esos métodos puede
   involucrar invocaciones de los métodos "open()" y "error()" de la
   instancia "OpenerDirector" padre.

3. Every handler with a method named like "<protocol>_response()" has
   that method called to post-process the response.


Objetos BaseHandler
===================

Los objetos "BaseHandler" proporcionan un par de métodos que son
útiles directamente y otros que están destinados a ser utilizados por
clases derivadas. Estos están pensados para uso directo:

BaseHandler.add_parent(director)

   Añade un director como padre.

BaseHandler.close()

   Elimina cualquier padre.

El siguiente atributo y los siguientes métodos sólo deben ser usados
por clases derivadas de "BaseHandler".

Nota:

  The convention has been adopted that subclasses defining
  "<protocol>_request()" or "<protocol>_response()" methods are named
  "*Processor"; all others are named "*Handler".

BaseHandler.parent

   Un "OpenerDirector" válido, el cual puede ser utilizado para abrir
   usando un protocolo diferente, o para manejar errores.

BaseHandler.default_open(req)

   Este método no es definido en "BaseHandler", pero las subclases
   deben definirlo si quieren cazar todas las URLs.

   This method, if implemented, will be called by the parent
   "OpenerDirector".  It should return a file-like object as described
   in the return value of the "open()" method of "OpenerDirector", or
   "None". It should raise "URLError", unless a truly exceptional
   thing happens (for example, "MemoryError" should not be mapped to
   "URLError").

   Este método será invocado antes de cualquier método de apertura
   específico de protocolo.

BaseHandler.<protocol>_open(req)

   Este método no está definido en "BaseHandler", pero las subclases
   deben definirlo si quieren manejar URLs con el protocolo dado.

   This method, if defined, will be called by the parent
   "OpenerDirector". Return values should be the same as for
   "default_open()".

BaseHandler.unknown_open(req)

   Este método *no* está definido en "BaseHandler", pero las subclases
   deben definirlo si quieren cazar todas las URLs sin manejador
   registrado para abrirlo.

   Este método, si está implementado, será invocado por el "parent" de
   "OpenerDirector". Los valores retornados deben ser los mismos que
   para "default_open()".

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

   Este método *no* está definido en "BaseHandler", pero las subclases
   deben sobreescribirlo si pretenden proporcionar una solución
   general para los errores HTTP que de otro modo no se manejarían.
   Sería invocado automáticamente por el "OpenerDirector" obteniendo
   el error y no debe ser invocado normalmente en otras
   circunstancias.

   *req* será un objeto "Request", *fp* será un objeto como archivo
   con el cuerpo de error HTTP, *code* será el código de error de tres
   dígitos, *msg* será la explicación visible para el usuario del
   código y *hdrs* será un objeto de mapeo con los encabezados del
   error.

   Los valores de retorno y las excepciones generadas deben ser los
   mismos que aquellos de "urlopen()".

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

   *nnn* debe ser un código de error HTTP de tres dígitos. Este método
   tampoco está definido en "BaseHandler", pero será invocado, si
   existe, en una instancia de una subclase, cuando ocurra un error
   HTTP con código *nnn*.

   Las subclases deben sobrescribir este método para manejar errores
   HTTP específicos.

   Arguments, return values and exceptions raised should be the same
   as for "http_error_default()".

BaseHandler.<protocol>_request(req)

   Este método *no* está definido en "BaseHandler", pero las subclases
   deben definirlo si pretenden preprocesar peticiones del protocolo
   dado.

   Este método, si está definido, será invocado por el
   "OpenerDirector" padre. *req* será un objeto "Request". El valor
   retornado debe ser un objeto "Request".

BaseHandler.<protocol>_response(req, response)

   Este método *no* está definido en "BaseHandler", pero las subclases
   deben definirlo si quieren postprocesar respuestas del protocolo
   dado.

   Este método, si está definido, será invocado por el
   "OpenerDirector" padre. *req* será un objeto "Request". *response*
   será un objeto que implementa la misma interfaz que el valor
   retornado de "urlopen()". El valor retornado debe implementar la
   misma interfaz que el valor retornado de "urlopen()".


Objetos HTTPRedirectHandler
===========================

Nota:

  Algunas redirecciones HTTP requieren acción desde el código del
  módulo del cliente. Si este es el caso, se genera "HTTPError". Vea
  **RFC 2616** para más detalles de los significados precisos de los
  diferentes códigos de redirección.An "HTTPError" exception raised as
  a security consideration if the HTTPRedirectHandler is presented
  with a redirected URL which is not an HTTP, HTTPS or FTP URL.

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

   Return a "Request" or "None" in response to a redirect. This is
   called by the default implementations of the "http_error_30*()"
   methods when a redirection is received from the server.  If a
   redirection should take place, return a new "Request" to allow
   "http_error_30*()" to perform the redirect to *newurl*.  Otherwise,
   raise "HTTPError" if no other handler should try to handle this
   URL, or return "None" if you can't but another handler might.

   Nota:

     La implementación predeterminada de este método no sigue
     estrictamente **RFC 2616**, la cual dice que las respuestas 301 y
     302 a peticiones POST no deben ser redirigidas automáticamente
     sin confirmación por el usuario. En realidad, los navegadores
     permiten redirección automática de esas respuestas, cambiando el
     POST a un "GET" y la implementación predeterminada reproduce este
     comportamiento.

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

   Redirecciona a la URL "Location:" o "URI:". Este método es invocado
   por el "OpenerDirector" padre al obtener una respuesta HTTP 'moved
   permanently'.

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

   Lo mismo que "http_error_301()", pero invocado para la respuesta
   'found'.

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

   Lo mismo que "http_error_301()", pero invocado para la respuesta
   'see other'.

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

   Lo mismo que "http_error_301()", pero invocado para la respuesta
   'redirección temporal'. No permite cambiar el método de solicitud
   de "POST" a "GET".

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

   Lo mismo que "http_error_301()", pero invocado para la respuesta
   'redirección permanente'. No permite cambiar el método de solicitud
   de "POST" a "GET".

   Nuevo en la versión 3.11.


Objetos HTTPCookieProcessor
===========================

Las instancias "HTTPCookieProcessor" tienen un atributo:

HTTPCookieProcessor.cookiejar

   El "http.cookiejar.CookieJar" en el cual las cookies están
   almacenadas.


Objetos ProxyHandler
====================

ProxyHandler.<protocol>_open(request)

   The "ProxyHandler" will have a method "<protocol>_open()" for every
   *protocol* which has a proxy in the *proxies* dictionary given in
   the constructor.  The method will modify requests to go through the
   proxy, by calling "request.set_proxy()", and call the next handler
   in the chain to actually execute the protocol.


Objetos HTTPPasswordMgr
=======================

Estos métodos están disponibles en los objetos "HTTPPasswordMgr" y
"HTTPPasswordMgrWithDefaultRealm".

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

   *uri* puede ser una única URI o una secuencia de URIs. *realm*,
   *user* y *passwd* deben ser cadenas. Esto causa que "(user,
   passwd)" se utilice como tokens de autenticación cuando la
   autenticación para *realm* y para una super URI de ninguna de las
   URIs dadas es provista.

HTTPPasswordMgr.find_user_password(realm, authuri)

   Obtener usuario/contraseña para el reino y URI dados, si alguno ha
   sido dado. Este método retornará "(None, None)" si no hay
   usuario/contraseña concordante.

   Para objetos "HTTPPasswordMgrWithDefaultRealm", el reino "None"
   será buscado si el *realm* dado no tiene usuario/contraseña
   concordante.


Objetos HTTPPasswordMgrWithPriorAuth
====================================

Esta manejador de contraseña extiende
"HTTPPasswordMgrWithDefaultRealm" para soportar el seguimiento de URIs
para las cuales deben ser enviadas siempre credenciales de
autenticación.

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

   *realm*, *uri*, *user*, *passwd* son como para
   "HTTPPasswordMgr.add_password()". *is_authenticated* establece el
   valor inicial del indicador "is_authenticated" para la URI o lista
   de URIs dadas. Si se especifica *is_authenticated* como "True",
   *realm* se ignora.

HTTPPasswordMgrWithPriorAuth.find_user_password(realm, authuri)

   Lo mismo que para objetos "HTTPPasswordMgrWithDefaultRealm"

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

   Actualiza el indicador "is_authenticated" para la *uri* o lista de
   URIs dadas.

HTTPPasswordMgrWithPriorAuth.is_authenticated(self, authuri)

   Retorna el estado actual del indicador "is_authenticated" para la
   URI dada.


Objetos AbstractBasicAuthHandler
================================

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

   Maneja una autenticación de petición obteniendo un par
   usuario/contraseña y reintentando la petición. *authreq* debe ser
   el nombre del encabezado donde la información sobre el reino se
   incluye en la petición, *host* especifica la URL y ruta para la
   cual autenticar, *req* debe ser el objeto "Request" (fallido) y
   *headers* deben ser los encabezados de error.

   *host* es una autoridad (ej. ""python.org"") o una URL conteniendo
   un componente de autoridad (ej. ""http://python.org/""). En
   cualquier caso, la autoridad no debe contener un componente
   userinfo (por lo que ""python.org"" y ""python.org:80"" están bien,
   ""joe:password@python.org"" no).


Objetos HTTPBasicAuthHandler
============================

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

   Reintenta la petición con la información de autenticación, si está
   disponible.


Objetos ProxyBasicAuthHandler
=============================

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

   Reintenta la petición con la información de autenticación, si está
   disponible.


Objetos AbstractDigestAuthHandler
=================================

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

   *authreq* debe ser el nombre del encabezado donde la información
   sobre el reino está incluida en la petición, *host* debe ser el
   host al que autenticar, *req* debe ser el objeto "Request"
   (fallido) y *headers* deben ser los encabezados de error.


Objetos HTTPDigestAuthHandler
=============================

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

   Reintenta la petición con la información de autenticación, si está
   disponible.


Objetos ProxyDigestAuthHandler
==============================

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

   Reintenta la petición con la información de autenticación, si está
   disponible.


Objetos HTTPHandler
===================

HTTPHandler.http_open(req)

   Envía una petición HTTP, que puede ser GET o POST, dependiendo de
   "req.has_data()".


Objetos HTTPSHandler
====================

HTTPSHandler.https_open(req)

   Envía una petición HTTPS, que puede ser GET o POST, dependiendo de
   "req.has_data()".


Objetos FileHandler
===================

FileHandler.file_open(req)

   Abre el archivo localmente, si no hay nombre de host, o el nombre
   de host es "'localhost'".

   Distinto en la versión 3.2: Este método es aplicable sólo para
   nombres de host locales. Cuando un nombre de host remoto es dado,
   se genera una excepción "URLError".


Objetos DataHandler
===================

DataHandler.data_open(req)

   Lee una URL de datos. Este tipo de URL contiene el contenido
   codificado en la URL misma. La sintaxis de la URL de datos se
   especifica en **RFC 2397**. Esta implementación ignora los espacios
   en blanco en datos codificados como base64 así que la URL puede ser
   envuelta en cualquier archivo fuente del que proviene. Pero a pesar
   de que a algunos navegadores no les importa si falta relleno al
   final de una URL codificada como base64, esta implementación
   lanzará un "ValueError" en este caso.


Objetos FTPHandler
==================

FTPHandler.ftp_open(req)

   Abre el archivo FTP indicado por *req*. El inicio de sesión siempre
   se realiza con un usuario y contraseña vacíos.


Objetos CacheFTPHandler
=======================

Los objetos "CacheFTPHandler" son objetos "FTPHandler" con los
siguientes métodos adicionales:

CacheFTPHandler.setTimeout(t)

   Establece el tiempo de expiración de conexiones a *t* segundos.

CacheFTPHandler.setMaxConns(m)

   Establece el número máximo de conexiones cacheadas a *m*.


Objetos UnknownHandler
======================

UnknownHandler.unknown_open()

   Genera una excepción "URLError".


Objetos HTTPErrorProcessor
==========================

HTTPErrorProcessor.http_response(request, response)

   Procesa errores de respuestas HTTP.

   Para códigos de error que no están en el rango de los 200, el
   objeto de respuesta es retornado inmediatamente.

   For non-200 error codes, this simply passes the job on to the
   "http_error_<type>()" handler methods, via
   "OpenerDirector.error()". Eventually, "HTTPDefaultErrorHandler"
   will raise an "HTTPError" if no other handler handles the error.

HTTPErrorProcessor.https_response(request, response)

   Procesa los errores HTTPS de las respuestas.

   Este comportamiento es el mismo que "http_response()".


Ejemplos
========

Adicionalmente a los ejemplos siguientes, se dan más ejemplos en HOWTO
- Cómo obtener recursos de Internet con el paquete urllib.

Este ejemplo obtiene la página principal python.org y despliega los
primeros 300 bytes de ella.

   >>> import urllib.request
   >>> with urllib.request.urlopen('http://www.python.org/') as f:
   ...     print(f.read(300))
   ...
   b'<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">\n\n\n<html
   xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">\n\n<head>\n
   <meta http-equiv="content-type" content="text/html; charset=utf-8" />\n
   <title>Python Programming '

Tenga en cuenta que urlopen retorna un objeto de bytes. Esto es porque
no hay forma para urlopen de determinar automáticamente la
codificación del flujo de bytes que recibe del servidor HTTP. En
general, un programa decodificará el objeto de bytes retornado a
cadena de caracteres una vez que determine o adivine la codificación
apropiada.

El siguiente documento W3C,
https://www.w3.org/International/O-charset, lista las diferentes
formas en la cual un documento (X)HTML o XML podría haber especificado
su información de codificación.

Ya que el sitio web python.org usa codificación *utf-8* tal y como se
especifica en su etiqueta meta, usaremos la misma para decodificar el
objeto de bytes.

   >>> with urllib.request.urlopen('http://www.python.org/') as f:
   ...     print(f.read(100).decode('utf-8'))
   ...
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtm

Es posible conseguir el mismo resultado sin usar la aproximación
*context manager*.

   >>> import urllib.request
   >>> f = urllib.request.urlopen('http://www.python.org/')
   >>> print(f.read(100).decode('utf-8'))
   <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtm

En el siguiente ejemplo, estamos enviando un flujo de datos a la
entrada estándar de un CGI y leyendo los datos que nos retorna. Tenga
en cuenta que este ejemplo sólo funcionará cuando la instalación de
Python soporte 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"

El código para el CGI de muestra usado en el ejemplo anterior es:

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

Aquí hay un ejemplo de realizar una petición "PUT" usando "Request":

   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)

Uso de Autenticación HTTP Básica:

   import urllib.request
   # Create an OpenerDirector with support for Basic HTTP Authentication...
   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)
   # ...and install it globally so it can be used with urlopen.
   urllib.request.install_opener(opener)
   urllib.request.urlopen('http://www.example.com/login.html')

"build_opener()" provides many handlers by default, including a
"ProxyHandler".  By default, "ProxyHandler" uses the environment
variables named "<scheme>_proxy", where "<scheme>" is the URL scheme
involved.  For example, the "http_proxy" environment variable is read
to obtain the HTTP proxy's URL.

Este ejemplo reemplaza el "ProxyHandler" predeterminado por uno que
usa URLs de proxy suministradas mediante programación y añade soporte
de autorización de proxy con "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)
   # This time, rather than install the OpenerDirector, we use it directly:
   opener.open('http://www.example.com/login.html')

Añadiendo encabezados HTTP:

Usa el argumento *headers* en el constructor de "Request", o:

   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: . . .)')
   r = urllib.request.urlopen(req)

"OpenerDirector" añade automáticamente un encabezado *User-Agent* a
cada "Request". Para cambiar esto:

   import urllib.request
   opener = urllib.request.build_opener()
   opener.addheaders = [('User-agent', 'Mozilla/5.0')]
   opener.open('http://www.example.com/')

También, recuerda que algunos encabezados estándar (*Content-Length*,
*Content-Type* y *Host*) son añadidos cuando se pasa "Request" a
"urlopen()" (o "OpenerDirector.open()").

Aquí hay un ejemplo de sesión que usa el método "GET" para obtener una
URL que contiene los parámetros:

   >>> 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'))
   ...

El siguiente ejemplo usa el método POST en su lugar. Tenga en cuenta
que la salida de parámetros desde urlencode es codificada a bytes
antes de ser enviados a urlopen como datos:

   >>> 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'))
   ...

El siguiente ejemplo usa un proxy HTTP especificado, sobrescribiendo
las configuraciones de entorno:

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

El siguiente ejemplo no usa proxies, sobrescribiendo las variables de
entorno:

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


Interfaz heredada
=================

Las siguientes funciones y clases están portadas desde el módulo
"urllib" de Python 2 (en oposición a "urllib2"). Ellas pueden estar
obsoletas en algún punto del futuro.

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

   Copy a network object denoted by a URL to a local file. If the URL
   points to a local file, the object will not be copied unless
   filename is supplied. Return a tuple "(filename, headers)" where
   *filename* is the local file name under which the object can be
   found, and *headers* is whatever the "info()" method of the object
   returned by "urlopen()" returned (for a remote object). Exceptions
   are the same as for "urlopen()".

   El segundo argumento, si está presente, especifica la localización
   a la que será copiada el objeto (si está ausente, la localización
   será un archivo temporal con un nombre generado). El tercer
   argumento, si está presente, es un objeto invocable que será
   invocado una vez que se establezca la conexión de red y después de
   eso una vez después de cada lectura de bloque. Al invocable se le
   pasarán tres argumentos; una cuenta de los bloques transferidos
   hasta el momento, un tamaño de bloque en bytes y el tamaño total
   del archivo. El tercer argumento puede ser "-1" en servidores FTP
   antiguos los cuales no retornan un tamaño de archivo en respuesta a
   una solicitud de recuperación.

   El siguiente ejemplo ilustra el escenario de uso más común:

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

   Si la *url* usa el esquema de identificador "http:", el argumento
   opcional *data* puede ser dado para especificar una petición "POST"
   (normalmente el tipo de petición es "GET"). El argumento *data*
   debe ser un objeto de bytes en formato *application/x-www-form-
   urlencoded*; vea la función "urllib.parse.urlencode()".

   "urlretrieve()" will raise "ContentTooShortError" when it detects
   that the amount of data available  was less than the expected
   amount (which is the size reported by a  *Content-Length* header).
   This can occur, for example, when the  download is interrupted.

   El *Content-Length* es tratado como un límite inferior: si no hay
   más datos a leer, urlretrieve lee más datos, pero si están
   disponibles menos datos, se genera la excepción.

   You can still retrieve the downloaded data in this case, it is
   stored in the "content" attribute of the exception instance.

   Si no fue proporcionado el encabezado *Content-Length*, urlretrieve
   no puede comprobar el tamaño de los datos que han sido descargados,
   y sólo los retorna. En este caso sólo tienes que asumir que la
   descarga fue exitosa.

urllib.request.urlcleanup()

   Limpia archivos temporales que pueden haber quedado tras llamadas
   anteriores a "urlretrieve()".

class urllib.request.URLopener(proxies=None, **x509)

   Obsoleto desde la versión 3.3.

   Clase base para apertura y lectura de URLs. A no ser que necesites
   soporte de apertura de objetos usando esquemas diferentes a
   "http:", "ftp:" o "file:", probablemente quieras usar
   "FancyURLopener".

   Por defecto, la clase "URLopener" envía un encabezado *User-Agent*
   de "urllib/VVV", donde *VVV* es el número de versión "urllib". Las
   aplicaciones pueden definir su propio encabezado *User-Agent*
   heredando de "URLopener" o "FancyURLopener" y estableciendo el
   atributo de clase "version" a un valor de cadena de caracteres
   apropiado en la definición de la subclase.

   El parámetro opcional *proxies* debe ser un diccionario mapeando
   nombres de esquemas a URLs de proxy, donde un diccionario vacío
   apaga los proxies completamente. Su valor predeterminado es "None",
   en cuyo caso las configuraciones de proxy del entorno serán usadas
   si están presentes, como ha sido discutido en la definición de
   "urlopen()", arriba.

   Parámetros adicionales de palabra clave, recogidos en *x509*,
   pueden ser usados por autenticación del cliente cuando usan el
   esquema "https:". Las palabras claves *key_file* y *cert_file*
   están soportadas para proveer una clave y certificado SSL; ambos
   son necesarias para soportar autenticación de cliente.

   Los objetos "URLopener" lanzarán una excepción "OSError" si el
   servidor retorna un código de error.

   open(fullurl, data=None)

      Abre *fullurl* usando el protocolo apropiado. Este método
      configura la información de caché e información de proxy,
      entonces invoca el método apropiado con sus argumentos de
      entrada. Si el esquema no está reconocido, se invoca
      "open_unknown()". El argumento *data* tiene el mismo significado
      que el argumento *data* de "urlopen()".

      Este método siempre entrecomilla *fullurl* usando "quote()".

   open_unknown(fullurl, data=None)

      Interfaz sobrescribible para abrir tipos de URL desconocidos.

   retrieve(url, filename=None, reporthook=None, data=None)

      Obtiene el contenido de *url* y lo coloca en *filename*. El
      valor retornado es una tupla que consiste de un nombre de
      archivo local y un objeto "email.message.Message" conteniendo
      los encabezados de respuesta (para URLs remotas) o "None" (para
      URLs locales). El invocador debe entonces abrir y leer los
      contenidos de *filename*. Si *filename* no está dado y la URL
      refiere a un archivo local, se retorna el nombre de archivo de
      entrada. Si la URL no es local y no se da *filename*, el nombre
      de archivo es la salida de la función "tempfile.mktemp()" con un
      sufijo que concuerda con el sufijo del último componente de la
      ruta de la URL de entrada. Si se da *reporthook*, debe ser una
      función que acepte tres parámetros numéricos: Un número de
      fragmento, se leen los fragmentos de tamaño máximo y el tamaño
      total de la descarga (-1 si es desconocida). Será invocada una
      vez al comienzo y después de que cada fragmento de datos sea
      leído de la red. *reporthook* es ignorado para URLs locales.

      Si la *url* usa el identificador de esquema "http:", el
      argumento opcional *data* puede ser dado para especificar una
      petición "POST" (normalmente el tipo de petición es "GET"). El
      argumento *data* debe estar en formato estándar *application/x
      -www-form-urlencoded*; vea la función
      "urllib.parse.urlencode()".

   version

      Variable que especifica el agente de usuario del objeto abridor.
      Para obtener "urllib" para decir a los servidores que es un
      agente de usuario particular, establece esto en una subclase
      como una variable de clase o en el constructor antes de invocar
      el constructor base.

class urllib.request.FancyURLopener(...)

   Obsoleto desde la versión 3.3.

   "FancyURLopener" hereda de "URLopener" proveyendo manejo
   predeterminado para los siguientes códigos de respuesta HTTP: 301,
   302, 303, 307 y 401. Para los códigos de respuesta 30x listados
   anteriormente, se usa el encabezado *Location* para obtener la URL
   actual. Para códigos de respuesta 401 (autenticación requerida), se
   realiza autenticación HTTP. Para los códigos de respuesta 30x, la
   recursión está limitada por el valor del atributo *maxentries*, el
   cual por defecto es 10.

   For all other response codes, the method "http_error_default()" is
   called which you can override in subclasses to handle the error
   appropriately.

   Nota:

     De acuerdo a la carta de **RFC 2616**, las respuestas a las
     peticiones POST 301 y 302 no debe ser redireccionadas
     automáticamente sin confirmación por el usuario. En realidad, los
     navegadores permiten redirección automática de esas respuestas,
     cambiando de POST a GET, y "urllib" reproduce este
     comportamiento.

   Los parámetros del constructor son el mismo que aquellos para
   "URLopener".

   Nota:

     Cuando se realiza autenticación básica, una instancia
     "FancyURLopener" invoca a su método "prompt_user_passwd()". La
     implementación predeterminada pregunta a los usuarios la
     información requerida en la terminal de control. Una subclase
     puede sobrescribir este método para soportar un comportamiento
     más apropiado si se necesita.

   La clase "FancyURLopener" ofrece un método adicional que debe ser
   sobrecargado para proveer el comportamiento apropiado:

   prompt_user_passwd(host, realm)

      Retorna la información necesaria para autenticar el usuario en
      el host dado en el reino de seguridad especificado. El valor
      retornado debe ser una tupla "(user, password)", la cual puede
      ser usada para autenticación básica.

      La implementación solicita esta información en el terminal; una
      aplicación debe sobrescribir este método para usar un modelo de
      interacción apropiado en el entorno local.


Restricciones "urllib.request"
==============================

* Actualmente, sólo uno de los siguientes protocolo están soportados:
  HTTP (versiones 0.9 y 1.0), FTP, archivos locales y URLs de datos.

  Distinto en la versión 3.4: Añadido soporte para URLs de datos.

* La característica de caché de "urlretrieve()" ha sido deshabilitada
  hasta que alguien encuentre el tiempo para hackear el procesamiento
  adecuado de los encabezados de tiempo de Expiración.

* Debería haber una función para consultar si una URL en particular
  está en la caché.

* Para compatibilidad con versiones anteriores, si una URL parece
  apuntar a un archivo local pero el archivo no puede ser abierto, la
  URL es reinterpretada usando el protocolo FTP. Esto a veces puede
  causar mensajes de error confusos.

* Las funciones "urlopen()" y "urlretrieve()" pueden causar retrasos
  arbitrariamente largos mientras esperan a que se configure una
  conexión de red. Esto significa que es difícil construir un cliente
  Web interactivo usando estas funciones sin utilizar hilos.

* Los datos retornados por "urlopen()" o "urlretrieve()" son los datos
  en crudo retornados por el servidor. Estos pueden ser datos binarios
  (como una imagen), texto plano o (por ejemplo) HTML. El protocolo
  HTTP provee información de tipo en el encabezado de respuesta, el
  cual puede ser inspeccionado mirando el encabezado *Content-Type*.
  Si los datos retornados son HTML, puedes usar el módulo
  "html.parser" para analizarlos.

* El código que maneja el protocolo FTP no puede diferenciar entre un
  archivo y un directorio. Esto puede llevar a un comportamiento
  inesperado cuando se intenta leer una URL que apunta a un archivo
  que no es accesible. Si la URL termina en un "/", se asume que se
  refiere a un directorio y será manejada acordemente. Pero si un
  intento de leer un archivo lleva a un error 550 (lo que significa
  que la URL no puede ser encontrada o no es accesible, a menudo por
  razones de permisos), entonces se trata la ruta como un directorio
  para manejar el caso cuando un directorio es especificado por una
  URL pero el "/" trasero ha sido dejado fuera. Esto puede causar
  resultados erróneos cuando intenta obtener un archivo cuyos permisos
  de lectura lo hacen inaccesible; el código FTP intentará leerlo,
  fallará con un error 550 y entonces realizará un listado de
  directorio para el archivo ilegible. Si se necesita un control más
  detallado, considere usar el módulo "ftplib", heredando
  "FancyURLopener" o cambiando *_urlopener* para ajustarlo a tus
  necesidades.


"urllib.response" --- Clases de respuesta usadas por urllib
***********************************************************

El módulo "urllib.response" define funciones y clases que definen una
interfaz mínima *file-like*, incluyendo "read()" y "readline()". Las
funciones definidas en este módulo son usadas internamente por el
módulo "urllib.request". El objeto de respuesta típico es una
instancia de "urllib.response.addinfourl":

class urllib.response.addinfourl

   url

      :URL del recurso obtenido, comúnmente usado para determinar si
      se ha seguido una redirección.

   headers

      Retorna las cabeceras de la respuesta en la forma de una
      instancia de "EmailMessage".

   status

      Nuevo en la versión 3.9.

      Código de estado  retornado por el servidor.

   geturl()

      Obsoleto desde la versión 3.9: Obsoleto en favor de "url".

   info()

      Obsoleto desde la versión 3.9: Obsoleto en favor de "headers".

   code

      Obsoleto desde la versión 3.9: Obsoleto en favor de "status".

   getcode()

      Obsoleto desde la versión 3.9: Obsoleto en favor de "status".
