【问题标题】:Gevent pool with nested web requests具有嵌套 Web 请求的 Gevent 池
【发布时间】:2013-03-10 13:23:08
【问题描述】:

我尝试组织最多 10 个并发下载的池。该函数应下载基本 url,然后解析该页面上的所有 url 并下载每个 url,但并发下载总数不应超过 10。

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)

我如何组织它以并发方式,但保持所有网络请求的一般全局池限制?

【问题讨论】:

    标签: python web pool gevent


    【解决方案1】:

    我认为以下内容应该可以满足您的需求。我在我的示例中使用 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.extend(soup.find_all('a'))
    
    for url in urls:
        jobs.append(p.spawn(get_links, url))
    gevent.joinall(jobs)
     
    

    【讨论】:

      【解决方案2】:

      gevent.pool 将限制并发的greenlets,而不是连接。

      你应该使用sessionHTTPAdapter

      连接限制 = 10 适配器 = requests.adapters.HTTPAdapter(pool_connections=connection_limit, pool_maxsize=connection_limit) 会话 = 请求。会话() session.mount('http://', 适配器) session.get('一些网址') # 或者用 gevent 做你的工作 从 gevent.pool 导入池 # 如果处理数据的时间应该大于连接限制 # 比唐宁长, # 进行更改运行处理。 池大小 = 15 池 = 池(池大小) 对于网址中的网址: pool.spawn(session.get, url)

      【讨论】:

      • 除了HTTPAdapter已经提供的连接池之外,您能否解释一下为什么使用gevent.pool。为什么不简单地使用 gevent.spawn(...)?非常感谢。
      【解决方案3】:

      您应该使用gevent.queue 以正确的方式进行操作。

      另外this(eventlet examples)将有助于你理解基本思想。

      Gevent 解决方案类似于 eventlet。

      记住会有地方存储访问过的URL,以免被循环,这样你就不会出现内存不足错误,你需要引入一些限制。

      【讨论】:

      • 问题是我有两种类型的 url,每一种都需要不同的功能来使用它。
      • 如果你需要不同的处理器(消费者)的url,那么将逻辑包装在生产者中,根据url的类型你应该产生一个特定的函数。但他们都有一个队列。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-09-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多