Я пишу веб-скребок на python, используя httplib2 и lxml (да - я знаю, что мог бы использовать scrapy. Давайте пройдем мимо этого ...) У скребка есть около 15000 страниц для разбора примерно на 400 000 элементов.У меня есть код для синтаксического анализа элементов, которые запускаются мгновенно (почти), но часть, которая загружает страницу с сервера, все еще очень медленная.Я хотел бы преодолеть это через параллелизм.Тем не менее, я не могу полагаться на КАЖДУЮ страницу, которую нужно анализировать КАЖДЫЙ раз.Я пытался с одним ThreadPool (например, multiprocessing.pool, но сделал с потоками - что должно быть хорошо, так как это процесс, связанный с вводом / выводом), но я не мог придумать изящный (или работающий) способ полученияВСЕ потоки останавливаются, когда дата последнего элемента индекса была больше, чем элемент, который мы обрабатывали.Прямо сейчас я работаю над методом, использующим два экземпляра ThreadPool - один для загрузки каждой страницы, а другой для анализа страниц.Пример упрощенного кода:
#! /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()
Запуск этого кода, однако, не делает то, что я ожидаю - то есть запускать два пула потоков: один заполняет очередь, а другой вытягивает ее для анализа.Он запускает пул сбора и проходит через него, а затем запускает parse_pool и проходит через него (я полагаю, я не позволил коду работать достаточно долго, чтобы добраться до parse_pool - дело в том, что collect_pool - это все, что кажется работающим).Я вполне уверен, что что-то напутал с порядком вызовов join (), но я не могу на всю жизнь понять, в каком порядке они должны быть. Мой вопрос, по сути, такой:Я лаю здесь правильное дерево?и если да, то, что, черт возьми, я делаю не так?Если я не - что бы вы предложили