2013-03-10 2 views
4

Я пытаюсь организовать пул с максимальными 10 одновременными загрузками. Функция должна загрузить базовый URL, то парсер всех URLs на этой странице и загрузить каждый из них, но общее количество одновременных загрузок не должно превышать 10.Пул Gevent с вложенными веб-запросами

from lxml import etree 
import gevent 
from gevent import monkey, pool 
import requests 

monkey.patch_all() 
urls = [ 
    'http://www.google.com', 
    'http://www.yandex.ru', 
    'http://www.python.org', 
    'http://stackoverflow.com', 
    # ... another 100 urls 
    ] 

LINKS_ON_PAGE=[] 
POOL = pool.Pool(10) 

def parse_urls(page): 
    html = etree.HTML(page) 
    if html: 
     links = [link for link in html.xpath("//a/@href") if 'http' in link] 
    # Download each url that appears in the main URL 
    for link in links: 
     data = requests.get(link) 
     LINKS_ON_PAGE.append('%s: %s bytes: %r' % (link, len(data.content), data.status_code)) 

def get_base_urls(url): 
    # Download the main URL 
    data = requests.get(url) 
    parse_urls(data.content) 

Как я могу организовать его идти параллельный путем, но сохранить общий глобальный лимит пула для ВСЕХ веб-запросов?

ответ

0

Вы должны использовать gevent.queue, чтобы сделать это в нужном тоне.

Также this(eventlet examples) поможет вам понять основную идею.

Решение Gevent похоже на eventlet.

Имейте в виду, что у вас будет где-то хранить посещенные URL-адреса, чтобы не ездить на велосипеде, поэтому вы не получите ошибку в памяти, вам нужно ввести некоторые ограничения.

+0

Проблема в том, что у меня есть 2 типа URL-адресов, и для каждого из них требуется другая функция для работы с ним. – DominiCane

+0

Если вам нужны разные процессоры (потребители) для URL-адресов, то заверните логику в производителе, в зависимости от типа URL-адреса вы должны создать определенную функцию. Но у всех есть одна очередь. –

4

gevent.pool ограничит параллельные зеленые, а не соединения.

Вы должны использовать session с HTTPAdapter

 
connection_limit = 10 
adapter = requests.adapters.HTTPAdapter(pool_connections=connection_limit, 
             pool_maxsize=connection_limit) 
session = requests.session() 
session.mount('http://', adapter) 
session.get('some url') 
# or do your work with gevent 
from gevent.pool import Pool 
# it should bigger than connection limit if the time of processing data 
# is longer than downings, 
# to give a change run processing. 
pool_size = 15 
pool = Pool(pool_size) 
for url in urls: 
    pool.spawn(session.get, url) 
+0

Не могли бы вы объяснить, почему вы используете gevent.pool в дополнение к пулу соединений, уже предоставленному HTTPAdapter. Почему бы просто не использовать gevent.spawn (...)? Большое спасибо. – ARF

+0

Ничего особенного. Легко управлять озерами в группе – kimjxie

4

Я думаю, что следующий должен получить, что вы хотите. Я использую BeautifulSoup в своем примере вместо того, что у вас есть.

from bs4 import BeautifulSoup 
import requests 
import gevent 
from gevent import monkey, pool 
monkey.patch_all() 

jobs = [] 
links = [] 
p = pool.Pool(10) 

urls = [ 
    'http://www.google.com', 
    # ... another 100 urls 
] 

def get_links(url): 
    r = requests.get(url) 
    if r.status_code == 200: 
     soup = BeautifulSoup(r.text) 
     links + soup.find_all('a') 

for url in urls: 
    jobs.append(p.spawn(get_links, url)) 
gevent.joinall(jobs) 
+0

Большое спасибо! Сотворил мою проблему! –

Смежные вопросы