| You are here: Inicio > Inmersión en Python > Servicios Web HTTP | << >> | ||||
Inmersión en PythonPython de novato a experto |
|||||
Hemos aprendido cosas sobre procesamiento de HTML y de XML, y por el camino también vio cómo descargar una página web y analizar XML de una URL, pero profundicemos algo más en el tema general de los servicios web HTTP.
Dicho sencillamente, los servicios web HTTP son formas programáticas de enviar y recibir datos a/desde servidores remotos usando directamente operaciones HTTP. Si queremos obtener datos del servidor usaremos HTTP GET; si queremos enviar datos nuevos usaremos HTTP POST. (Algunos API más avanzados de servicios web HTTP también definen maneras para modificar y eliminar datos existentes, usando HTTP PUT y HTTP DELETE). En otras palabras, los “verbos” que incorpora el protocolo HTTP (GET, POST, PUT y DELETE) se relacionan directamente con las operaciones de las aplicaciones para recibir, enviar, modificar y borrar datos.
La ventaja principal de este enfoque es la simplicidad, y esta simplicidad ha resultado ser popular en muchos sitios diferentes. Se pueden crear y almacenar de forma estática los datos (normalmente XML), o generarlos de forma dinámica mediante un script en el servidor, y todos los lenguajes más usados incluyen bibliotecas HTTP para descargarlos. La depuración también es sencilla porque se puede cargar el servicio web en cualquier servidor web y ver los datos sin tratar. Los navegadores modernos incluso dan un formato de aspecto agradable a los datos XML, para permitirle navegar por ellos rápidamente.
Ejemplos de servicios web puros XML-sobre-HTTP:
En próximos capítulos explorará APIs que usan HTTP como transporte para enviar y recibir datos, pero no relacionará la semántica de la aplicación a la propia de HTTP (hacen todo usando HTTP POST). Pero este capítulo se concentrará en usar HTTP GET para obtener datos de un servidor remoto, y exploraremos varias características de HTTP que podemos usar para obtener el máximo beneficio de los servicios web puramente HTTP.
Aquí tiene una versión más avanzada del módulo openanything que vio en el capítulo anterior:
Si aún no lo ha hecho, puede descargar éste ejemplo y otros usados en este libro.
import urllib2, urlparse, gzip from StringIO import StringIO USER_AGENT = 'OpenAnything/1.0 +http://diveintopython.org/http_web_services/' class SmartRedirectHandler(urllib2.HTTPRedirectHandler): def http_error_301(self, req, fp, code, msg, headers): result = urllib2.HTTPRedirectHandler.http_error_301( self, req, fp, code, msg, headers) result.status = code return result def http_error_302(self, req, fp, code, msg, headers): result = urllib2.HTTPRedirectHandler.http_error_302( self, req, fp, code, msg, headers) result.status = code return result class DefaultErrorHandler(urllib2.HTTPDefaultErrorHandler): def http_error_default(self, req, fp, code, msg, headers): result = urllib2.HTTPError( req.get_full_url(), code, msg, headers, fp) result.status = code return result def openAnything(source, etag=None, lastmodified=None, agent=USER_AGENT): '''URL, filename, or string --> stream This function lets you define parsers that take any input source (URL, pathname to local or network file, or actual data as a string) and deal with it in a uniform manner. Returned object is guaranteed to have all the basic stdio read methods (read, readline, readlines). Just .close() the object when you're done with it. If the etag argument is supplied, it will be used as the value of an If-None-Match request header. If the lastmodified argument is supplied, it must be a formatted date/time string in GMT (as returned in the Last-Modified header of a previous request). The formatted date/time will be used as the value of an If-Modified-Since request header. If the agent argument is supplied, it will be used as the value of a User-Agent request header. ''' if hasattr(source, 'read'): return source if source == '-': return sys.stdin if urlparse.urlparse(source)[0] == 'http': # open URL with urllib2 request = urllib2.Request(source) request.add_header('User-Agent', agent) if etag: request.add_header('If-None-Match', etag) if lastmodified: request.add_header('If-Modified-Since', lastmodified) request.add_header('Accept-encoding', 'gzip') opener = urllib2.build_opener(SmartRedirectHandler(), DefaultErrorHandler()) return opener.open(request) # try to open with native open function (if source is a filename) try: return open(source) except (IOError, OSError): pass # treat source as string return StringIO(str(source)) def fetch(source, etag=None, last_modified=None, agent=USER_AGENT): '''Fetch data and metadata from a URL, file, stream, or string''' result = {} f = openAnything(source, etag, last_modified, agent) result['data'] = f.read() if hasattr(f, 'headers'): # save ETag, if the server sent one result['etag'] = f.headers.get('ETag') # save Last-Modified header, if the server sent one result['lastmodified'] = f.headers.get('Last-Modified') if f.headers.get('content-encoding', '') == 'gzip': # data came back gzip-compressed, decompress it result['data'] = gzip.GzipFile(fileobj=StringIO(result['data']])).read() if hasattr(f, 'url'): result['url'] = f.url result['status'] = 200 if hasattr(f, 'status'): result['status'] = f.status f.close() return result
<< Resumen |
| 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | |
Cómo no obtener datos mediante HTTP >> |