使用urllib2或其他HTTP库进行多个(异步)连接?

14 投票
6 回答
16667 浏览
提问于 2025-04-16 06:42

我有这样的代码。

for p in range(1,1000):
    result = False
    while result is False:
        ret = urllib2.Request('http://server/?'+str(p))
        try:
            result = process(urllib2.urlopen(ret).read())
        except (urllib2.HTTPError, urllib2.URLError):
            pass
    results.append(result)

我想同时发出两到三个请求,这样可以加快速度。我可以用urllib2来实现吗?如果不行,那我应该用哪个库呢?谢谢。

6 个回答

9

看看这个 gevent —— 这是一个基于协程的Python网络库,它使用greenlet来在libevent事件循环之上提供一个高级的同步接口。

示例:

#!/usr/bin/python
# Copyright (c) 2009 Denis Bilenko. See LICENSE for details.

"""Spawn multiple workers and wait for them to complete"""

urls = ['http://www.google.com', 'http://www.yandex.ru', 'http://www.python.org']

import gevent
from gevent import monkey

# patches stdlib (including socket and ssl modules) to cooperate with other greenlets
monkey.patch_all()

import urllib2


def print_head(url):
    print 'Starting %s' % url
    data = urllib2.urlopen(url).read()
    print '%s: %s bytes: %r' % (url, len(data), data[:50])

jobs = [gevent.spawn(print_head, url) for url in urls]

gevent.joinall(jobs)
10

你可以使用异步输入输出(IO)来实现这个功能。

requests 加上 gevent 就可以得到 grequests

GRequests 让你可以轻松地用 Requests 和 Gevent 一起发起异步的 HTTP 请求。

import grequests

urls = [
    'http://www.heroku.com',
    'http://tablib.org',
    'http://httpbin.org',
    'http://python-requests.org',
    'http://kennethreitz.com'
]

rs = (grequests.get(u) for u in urls)
grequests.map(rs)
11

所以,现在是2016年,我们有了Python 3.4及以上版本,里面自带了一个叫做asyncio的模块,可以用来处理异步输入输出。我们还可以使用aiohttp作为HTTP客户端,来同时下载多个网址。

import asyncio
from aiohttp import ClientSession

async def fetch(url):
    async with ClientSession() as session:
        async with session.get(url) as response:
            return await response.read()

async def run(loop, r):
    url = "http://localhost:8080/{}"
    tasks = []
    for i in range(r):
        task = asyncio.ensure_future(fetch(url.format(i)))
        tasks.append(task)

    responses = await asyncio.gather(*tasks)
    # you now have all response bodies in this variable
    print(responses)

loop = asyncio.get_event_loop()
future = asyncio.ensure_future(run(loop, 4))
loop.run_until_complete(future)

来源:复制自http://pawelmhm.github.io/asyncio/python/aiohttp/2016/04/22/asyncio-aiohttp.html

撰写回答