2013-03-10 56 views
4

我嘗試組織最多10個併發下載的池。該函數應該下載基地網址,然後解析器此頁面上的所有網址,並下載他們每個人,但併發下載的總數應不超過10具有嵌套web請求的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種類型的網址,每個網址都需要不同的功能才能使用它。 – DominiCane 2013-03-10 14:27:25

+0

如果你需要不同的處理器(消費者)爲urls,然後根據你應該產生一個特定的功能url的類型包裝在生產者的邏輯。但他們都有一個隊列。 – 2013-03-10 14:57:06

4

gevent.pool將限制併發greenlet,而不是連接。

你應該使用sessionHTTPAdapter

 
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

您能解釋一下爲什麼除了HTTPAdapter已經提供的連接池外,還使用了gevent.pool。爲什麼不簡單地使用gevent.spawn(...)?非常感謝。 – ARF 2013-11-03 18:08:08

+0

沒什麼特別的。在羣組中管理greenlet很容易 – kimjxie 2013-11-05 14:02:57

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

非常感謝,非常有用!解決了我的問題! – 2017-01-07 09:34:34