Python并发请求之requests_future模块使用

requests_future是requests模块和concurrent.futures模块的综合,使用这个模块可以轻松实现异步并发。目前在github已经有1.5K的star了。

安装

pip3 install requests_future

使用例子

# -*- coding: utf-8 -*-
# @Time : 2019-12-09 10:00
# @Author : cxa
# @File : demo.py
# @Software: PyCharm
from requests_futures.sessions import FuturesSession
from concurrent.futures import as_completed
from lxml import html
import time

url = ["http://www.baidu.com", "http://www.163.com", "http://www.google.com", "http://www.cnblogs.com/c-x-a"]


def get_node(source, x=".//head/title//text()"):
    root = html.fromstring(source)
    node = root.xpath(x)
    return node


def response_hook(resp, *args, **kwargs):
    start = time.time()
    resp.encoding = resp.apparent_encoding
    resp.data = resp.text
    resp.code = resp.status_code
    resp.headers = resp.headers
    resp.elapsed = time.time() - start


def get_req():
    with FuturesSession(max_workers=4) as session:
        futures = [session.get(i, hooks={"response": response_hook}) for i in url]
        for future in as_completed(futures):
            resp = future.result()
            print("状态码", resp.code)
            print("标题", get_node(resp.data)[0])
            print("耗时", resp.elapsed)
            print("="*30)

if __name__ == '__main__':
    get_req()

首先通过导入FuturesSession,然后通过 with FuturesSession(max_workers=4) as session:创建一个上下文, 保证在并发请求之后关闭资源,然后就像使用session.get传入url等参数,除此之处,还可以传入一个hooks字典,
其值是一个函数。这个函数会在请求结束后执行一系列操作,具体看我的response_hook函数就好了。
接下来我们就获取一个future对象列表futures。可以使用concurrent.futures的as_completed,as_completed()可以把多个并发的协程一起给它,它把返回的结果变成一个生成器,每次返回一个协程的结果,与函数wait()一样,执行协程是乱序的,不会等所有协程执行完成才返回。

我们还可以继承FuturesSession,然后重写上面的过程,代码如下

from requests_futures.sessions import FuturesSession
from concurrent.futures import as_completed
from lxml import html
import time

url = ["http://www.baidu.com", "http://www.163.com", "http://www.google.com", "http://www.cnblogs.com/c-x-a"]


class MySession(FuturesSession):

    def request(self, method, url, hooks=None, *args, **kwargs):
        start = time.time()
        if hooks is None:
            hooks = {}

        def response_hook(resp, *args, **kwargs):
            resp.encoding = resp.apparent_encoding
            resp.data = resp.text
            resp.code = resp.status_code
            resp.headers = resp.headers
            resp.elapsed = time.time() - start

        try:
            if isinstance(hooks['response'], (list, tuple)):
                hooks['response'].insert(0, response_hook)
            else:
                hooks['response'] = [response_hook, hooks['response']]
        except KeyError:
            hooks['response'] = response_hook

        return super(MySession, self).request(method, url, hooks=hooks, *args, **kwargs)


def get_node(source, x=".//head/title//text()"):
    root = html.fromstring(source)
    node = root.xpath(x)
    return node


def get_req():
    headers = {
        'Accept': 'application/json, text/javascript, */*; q=0.01',
        'Accept-Encoding': 'gzip, deflate',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'User-Agent': "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.87 Safari/537.36",
    }
    with MySession(max_workers=4) as session:
        futures = [session.get(i, headers=headers) for i in url]
        for future in as_completed(futures):
            resp = future.result()
            print("状态码", resp.code)
            print("标题", get_node(resp.data)[0])
            print("耗时", resp.elapsed)
            print("=" * 30)



if __name__ == '__main__':
    get_req()

这就是关于requests_futures的模块的简单使用案例,因为创建出session之后,剩下的和requests模块的session没多少差别,就不仔细说了,这样没啥难度就可以轻松实现并发了,也可以使用之前我说的tomorrow模块进行并发,不过tomorrow只有线程池的支持,requests_futures好处是还支持进程池,所以我打算抛弃tomorrow模块了。

参考资料

https://github.com/ross/requests-futures

推荐阅读

Python 爬虫面试题 170 道:2019 版

python并发模块之concurrent.futures(一)

python并发爬虫利器tomorrow

爬虫必备-如何使用Chrome DevTools花式打断点

添加微信[gopython3].回复:回复Go或者Python加对应技术群

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 如果你想在 Python 中发送高并发的 HTTP 请求,你可以使用并发库来实现。 Python 标准库中有两个模块可以实现高并发的 HTTP 请求: - `threading` 模块使用线程来实现高并发。 - `concurrent.futures` 模块使用进程或线程来实现高并发。 下面是一个使用 `concurrent.futures` 模块发送 HTTP 请求的示例: ``` import concurrent.futures import requests urls = [ 'http://www.example.com/1', 'http://www.example.com/2', 'http://www.example.com/3', ] def fetch(url): response = requests.get(url) return response.text with concurrent.futures.ThreadPoolExecutor() as executor: results = [executor.submit(fetch, url) for url in urls] for future in concurrent.futures.as_completed(results): print(future.result()) ``` 在这个例子中,我们使用了 `ThreadPoolExecutor` 来创建一个线程池,然后使用 `submit` 方法提交 HTTP 请求。当所有的请求都完成之后,我们使用 `as_completed` 方法来遍历结果,并打印出来。 还有很多其他的方法可以用来实现高并发的 HTTP 请求,比如使用异步 IO 库(如 `asyncio` 或 `trio`)或者使用 HTTP 库(如 `aiohttp` 或 `httptools`)。 ### 回答2: Python并发HTTP请求可以使用多线程或者协程来实现。在Python标准库中,可以使用`threading`模块实现多线程,或者使用`asyncio`模块实现协程。 使用多线程实现高并发HTTP请求的方法是,创建多个线程,每个线程负责发送一个HTTP请求,并且可以通过设置线程数来控制并发数。可以使用`requests`库来发送HTTP请求使用`ThreadPoolExecutor`来管理线程池,并且使用`Future`来获取线程的返回结果。具体步骤如下: 1.首先,导入所需的模块:`import threading`、`from concurrent.futures import ThreadPoolExecutor`、`import requests` 2.创建一个线程池:`executor = ThreadPoolExecutor(max_workers=10)`,这里设置线程数为10,可以根据需要进行调整。 3.定义一个HTTP请求函数:`def send_request(url):`,使用`requests`库发送HTTP请求,并返回响应结果。 4.创建多个线程,并将线程添加到线程池中:`task = executor.submit(send_request, url)`,其中`url`为要发送的HTTP请求地址。 5.获取线程的返回结果:`result = task.result()`,这里会阻塞直到线程返回结果。 使用协程实现高并发HTTP请求可以使用`asyncio`模块来实现。协程通过`asyncio`模块的事件循环来管理,使用`aiohttp`库发送HTTP请求,并使用`async`和`await`关键字进行异步操作。具体步骤如下: 1.首先,导入所需的模块:`import asyncio`、`import aiohttp` 2.定义一个协程函数:`async def send_request(url):`,使用`aiohttp`库发送HTTP请求,并返回响应结果。 3.创建一个事件循环:`loop = asyncio.get_event_loop()`。 4.使用`asyncio.gather()`函数创建多个协程任务:`tasks = [send_request(url) for url in urls]`,其中`urls`为要发送的HTTP请求地址列表。 5.通过事件循环运行协程任务:`results = loop.run_until_complete(asyncio.gather(*tasks))`,这里会阻塞直到所有协程任务完成,并返回结果列表。 通过以上两种方法,可以实现Python的高并发HTTP请求。多线程适用于IO密集型的应用场景,而协程适用于CPU密集型的应用场景。开发者可以根据具体的业务需求选择合适的方法来实现高并发的HTTP请求。 ### 回答3: Python并发HTTP请求是指在Python编程语言中实现同时发送多个HTTP请求的能力。可以通过多种方式实现高并发的HTTP请求,下面介绍两种常用的方法。 1. 使用多线程:通过创建多个线程,每个线程负责发送一个HTTP请求,这样可以同时进行多个请求,提高并发性能。可以使用Python的内置模块`threading`来实现多线程,并使用第三方库`requests`来进行HTTP请求。首先导入相关模块,然后创建线程并启动,最后等待所有线程执行完成: ```python import threading import requests def send_request(url): response = requests.get(url) print(response.text) threads = [] urls = ['http://example.com/url1', 'http://example.com/url2', 'http://example.com/url3'] for url in urls: thread = threading.Thread(target=send_request, args=(url,)) threads.append(thread) thread.start() for thread in threads: thread.join() ``` 2. 使用协程:使用协程可以避免线程切换的开销,提高并发量。可以使用第三方库`gevent`来实现协程,并使用`requests`库进行HTTP请求。首先导入相关模块,然后使用协程来发送HTTP请求,最后等待所有协程执行完成。 ```python import gevent from gevent import monkey monkey.patch_all() import requests def send_request(url): response = requests.get(url) print(response.text) urls = ['http://example.com/url1', 'http://example.com/url2', 'http://example.com/url3'] jobs = [gevent.spawn(send_request, url) for url in urls] gevent.joinall(jobs) ``` 以上是两种常用的方法,可以根据实际情况选择适合的方式来实现Python并发HTTP请求

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值