Estoy escribiendo un raspador web en python, usando httplib2 y lxml (sí, sé que podría estar usando scrapy. Pasemos eso ...) El raspador tiene alrededor de 15000 páginas para analizar aproximadamente 400,000 artículos. Tengo el código para analizar los elementos para que se ejecuten de forma instantánea (casi), pero la parte que descarga la página del servidor sigue siendo extremadamente lenta. Me gustaría superar eso a través de la concurrencia. Sin embargo, no puedo confiar en CADA página que deba analizarse CADA vez. Lo he intentado con un solo ThreadPool (como multiprocesamiento.pool, pero hecho con hilos, lo que debería estar bien ya que se trata de un proceso de E/S enlazado), pero no se me ocurrió una forma elegante de obtener TODOS los hilos para detener cuando la fecha del último elemento de índice era mayor que el artículo que estábamos procesando. En este momento, estoy trabajando en un método que utiliza dos instancias de ThreadPool: una para descargar cada página y otra para analizar las páginas. Un ejemplo de código simplificado es:Python - múltiples grupos de hilos simultáneos
#! /usr/bin/env python2
import httplib2
from Queue import PriorityQueue
from multiprocessing.pool import ThreadPool
from lxml.html import fromstring
pages = [x for x in range(1000)]
page_queue = PriorityQueue(1000)
url = "http://www.google.com"
def get_page(page):
#Grabs google.com
h = httplib2.Http(".cache")
resp, content = h.request(url, "GET")
tree = fromstring(str(content), base_url=url)
page_queue.put((page, tree))
print page_queue.qsize()
def parse_page():
page_num, page = page_queue.get()
print "Parsing page #" + str(page_num)
#do more stuff with the page here
page_queue.task_done()
if __name__ == "__main__":
collect_pool = ThreadPool()
collect_pool.map_async(get_page, pages)
collect_pool.close()
parse_pool = ThreadPool()
parse_pool.apply_async(parse_page)
parse_pool.close()
parse_pool.join()
collect_pool.join()
page_queue.join()
La ejecución de este código sin embargo, no hago lo que espero - que es de disparar dos threadpools: uno poblar una cola y otro tirando de ella para analizar. Comienza el grupo de recopilación y lo ejecuta, y luego comienza el parse_pool y lo ejecuta (supongo que no he permitido que el código se ejecute el tiempo suficiente para llegar a parse_pool; el punto es que collect_pool es todo lo que parece estar ejecutándose)) Estoy bastante seguro de haber arruinado algo con el orden de las llamadas para unirme(), pero no puedo por la vida de mí averiguar en qué orden se supone que deben estar. Mi pregunta es esencialmente esta: : ¿Estoy ladrando el árbol correcto aquí? y si es así, ¿qué demonios estoy haciendo mal? Si no lo soy, ¿cuáles serían sus sugerencias
map_async - bloquea hasta que se procese todo el trabajo. –
Eso aborda formalmente por qué no funciona, pero no responde necesariamente a toda mi pregunta, que se reduce a "¿Es esto una manera loca de hacer esto?". Si la respuesta es 'no', estoy cerca y solo necesito perfeccionar mis métodos para hacerlo. En caso afirmativo, me gustaría algunos consejos sobre cómo puedo lograr esto 'correctamente'. – bbenne10