2011-04-27 15 views
16

Me está costando mucho tiempo que las solicitudes HTTPS asíncronas/enhebradas funcionen utilizando el urllib2 de Python.Python - Ejemplo de solicitud asíncrona/subprocesada de urllib2 mediante HTTPS

¿Alguien tiene un ejemplo básico que implementa urllib2.Request, urllib2.build_opener y una subclase de urllib2.HTTPSHandler?

Gracias!

+1

bienvenido a SO ... do ** you ** tiene un ejemplo de lo que no funciona para usted actualmente? Puede ser más fácil de diagnosticar que comenzar de cero en una respuesta aquí ... –

+2

¿Hay alguna regla que indique que toda pregunta debe ser "depurar mi código"? Mi código está lleno de referencias locas a variables que prefiero no explicar, URL sensibles, etc. Estas son 10 líneas de código para alguien que sabe cómo hacerlo. – SeaTurtle

+0

Veo que no hay una respuesta aceptada. ¿Todavía estás interesado en esto? He resuelto este problema hace unos días, así que podría tomarme el tiempo para escribir una respuesta detallada con el código. – MestreLion

Respuesta

10

El código siguiente realiza 7 solicitudes HTTP de forma asincrónica al mismo tiempo. No usa subprocesos, en su lugar utiliza una red asincrónica con la biblioteca twisted.

from twisted.web import client 
from twisted.internet import reactor, defer 

urls = [ 
'http://www.python.org', 
'http://stackoverflow.com', 
'http://www.twistedmatrix.com', 
'http://www.google.com', 
'http://launchpad.net', 
'http://github.com', 
'http://bitbucket.org', 
] 

def finish(results): 
    for result in results: 
     print 'GOT PAGE', len(result), 'bytes' 
    reactor.stop() 

waiting = [client.getPage(url) for url in urls] 
defer.gatherResults(waiting).addCallback(finish) 

reactor.run() 
+1

Preferiría no distribuir mi script con un requisito de Twisted. ¿Puedes hacer esto con los complementos urllib2.Request, urllib2.build_opener y una subclase de urllib2.HTTPSHandler? – SeaTurtle

+0

@SeaTurtle: Twisted es de código abierto y está escrito en python puro. Puede hacer que las partes relevantes se tuerzan e incluir en su código. En otras palabras, considere *** twisted ** itself * como el ejemplo de cómo hacerlo con built-in. – nosklo

0

aquí es el código de eventlet

urls = ["http://www.google.com/intl/en_ALL/images/logo.gif", 
    "https://wiki.secondlife.com/w/images/secondlife.jpg", 
    "http://us.i1.yimg.com/us.yimg.com/i/ww/beta/y3.gif"] 

import eventlet 
from eventlet.green import urllib2 

def fetch(url): 

    return urllib2.urlopen(url).read() 

pool = eventlet.GreenPool() 

for body in pool.imap(fetch, urls): 
    print "got body", len(body) 
+0

Hola, preferiría no distribuir mi script con un requisito de evento. ¿Puedes hacer esto con los complementos urllib2.Request, urllib2.build_opener y una subclase de urllib2.HTTPSHandler? – SeaTurtle

+0

No, eso no es posible. Además, si tengo razón, solo funciona bajo Linux. –

5

aquí es un ejemplo usando urllib2 (con https) y roscas. Cada hilo recorre una lista de URL y recupera el recurso.

import itertools 
import urllib2 
from threading import Thread 


THREADS = 2 
URLS = (
    'https://foo/bar', 
    'https://foo/baz', 
    ) 


def main(): 
    for _ in range(THREADS): 
     t = Agent(URLS) 
     t.start() 


class Agent(Thread): 
    def __init__(self, urls): 
     Thread.__init__(self) 
     self.urls = urls 

    def run(self): 
     urls = itertools.cycle(self.urls) 
     while True: 
      data = urllib2.urlopen(urls.next()).read() 


if __name__ == '__main__': 
    main() 
8

hay una manera muy simple, que implica un controlador para urllib2, que se puede encontrar aquí: http://pythonquirks.blogspot.co.uk/2009/12/asynchronous-http-request.html

#!/usr/bin/env python 

import urllib2 
import threading 

class MyHandler(urllib2.HTTPHandler): 
    def http_response(self, req, response): 
     print "url: %s" % (response.geturl(),) 
     print "info: %s" % (response.info(),) 
     for l in response: 
      print l 
     return response 

o = urllib2.build_opener(MyHandler()) 
t = threading.Thread(target=o.open, args=('http://www.google.com/',)) 
t.start() 
print "I'm asynchronous!" 

t.join() 

print "I've ended!" 
+4

Solo me gustaría advertir que, si bien este método es fácil y rápido, es muy propenso a problemas cuando algo se rompe (por ejemplo, la URL no está disponible). Hay una buena guía para principiantes sobre cómo enhebrar en http://www.ibm.com/developerworks/aix/library/au-threadingpython/ que incluye un ejemplo muy simple de una solución Async urllib2. – stricjux

1

Puede utilizar S asíncrona para hacer esto.

requests + gevent = grequests

GRequests le permite utilizar solicitudes con GEvent para realizar peticiones HTTP asíncronas fácilmente.

import grequests 

urls = [ 
    'http://www.heroku.com', 
    'http://tablib.org', 
    'http://httpbin.org', 
    'http://python-requests.org', 
    'http://kennethreitz.com' 
] 

rs = (grequests.get(u) for u in urls) 
grequests.map(rs)