Python中有许多HTTP客户端。使用最广泛且最容易的是requests。

持续连接

很多人学习python,不知道从何学起。
很多人学习python,掌握了基本语法过后,不知道在哪里寻找案例上手。
很多已经做案例的人,却不知道如何去学习更加高深的知识。
那么针对这三类人,我给大家提供一个好的学习平台,免费领取视频教程,电子书籍,以及课程的源代码!
QQ群:1097524789

持续连接是自HTTP 1.1以来的标准,尽管许多应用程序并未使用它们。以简单模式使用请求时(例如使用get函数),连接会在返回时关闭,Session对象允许重用已经打开的连接。

import requests
session = requests.Session()
session.get("https://china-testing.github.io/")
# Connection is re-used
session.get("https://china-testing.github.io/")

每个连接都存储在连接池中(默认为10)

import requests
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(
pool_connections=100,
pool_maxsize=100)
session.mount('http://', adapter)
response = session.get("http://example.org")

重用TCP连接有许多性能优势:

  • 降低CPU和内存使用率(同时打开的连接较少)。

  • 减少了后续请求中的延迟(无TCP握手)。

  • 可以引发异常而不会关闭TCP连接。

HTTP协议还提供了流水线,流水线化允许在同一连接上发送多个请求,而无需等待答复(批处理)。不幸的是,请求库不支持此功能。但是,流水线请求可能不如并行发送它们那么快。实际上,HTTP 1.1协议强制以与发送请求相同的顺序发送答复-先进先出。

并行

requests的主要缺点是同步的。调用requests.get("http://example.org")会阻塞程序,直到HTTP服务器完全答复为止。可以通过使用并发线程提供的线程池来缓解此问题。它允许以非常快速的方式并行化HTTP请求。

from concurrent import futures
import requests
with futures.ThreadPoolExecutor(max_workers=4) as executor:
futures = [
executor.submit(
lambda: requests.get("http://example.org"))
for _ in range(8) ]
results = [
f.result().status_code
for f in futures]
print("Results: %s" % results)

也可以借助requests-futures的库:

来自requests_futures导入会话

from requests_futures import sessions

session = sessions.FuturesSession()

futures = [
session.get("http://example.org")
for _ in range(8)
]

results = [
f.result().status_code
for f in futures
]

print("Results: %s" % results)

在请求中使用期货

默认情况下,创建具有两个线程的工作程序,但是程序可以通过将max_workers参数甚至是自己的执行程序传递给FuturSession对象来轻松自定义此值,例如:FuturesSession(executor=ThreadPoolExecutor(max_workers=10))。

异步

如前所述,请求是完全同步的。这会在等待服务器回复时阻止应用程序,从而降低程序速度。在线程中发出HTTP请求是一种解决方案,但是线程确实有其自身的开销,这暗示着并行性,这并不是每个人总是很高兴在程序中看到的东西。

从版本3.5开始,Python使用异步将异步作为其核心。aiohttp库提供了一个基于asyncio之上的异步HTTP客户端。该库允许按顺序发送请求,但无需等待答复回来再发送新请求。与HTTP流水形成对比,aiohttp通过多个连接并行发送请求,避免了前面解释的排序问题。


import aiohttp
import asyncio
async def get(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return response
loop = asyncio.get_event_loop()
coroutines = [get("https://china-testing.github.io/") for _ in range(8)]
results = loop.run_until_complete(asyncio.gather(*coroutines))
print("Results: %s" % results)

所有这些解决方案都提供了不同的方法来提高HTTP客户端的速度。

性能

下面的代码向HTTPbin.org发送请求。本示例实现了上面列出的所有技术并对它们进行计时。


import contextlib
import time
import aiohttp
import asyncio
import requests
from requests_futures import sessions
URL = "http://httpbin.org/delay/1"
TRIES = 10
@contextlib.contextmanager
def report_time(test):
t0 = time.time()
yield
print("Time needed for `%s' called: %.2fs"
% (test, time.time() - t0))
with report_time("serialized"):
for i in range(TRIES):
requests.get(URL)
session = requests.Session()
with report_time("Session"):
for i in range(TRIES):
session.get(URL)
session = sessions.FuturesSession(max_workers=2)
with report_time("FuturesSession w/ 2 workers"):
futures = [session.get(URL)
for i in range(TRIES)]
for f in futures:
f.result()
session = sessions.FuturesSession(max_workers=TRIES)
with report_time("FuturesSession w/ max workers"):
futures = [session.get(URL)
for i in range(TRIES)]
for f in futures:
f.result()
async def get(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
await response.read()
loop = asyncio.get_event_loop()
with report_time("aiohttp"):
loop.run_until_complete(
asyncio.gather(*[get(URL)
for i in range(TRIES)]))

运行此程序将给出以下输出:

Time needed for `serialized' called: 12.12s
Time needed for `Session' called: 11.22s
Time needed for `FuturesSession w/ 2 workers' called: 5.65s
Time needed for `FuturesSession w/ max workers' called: 1.25s
Time needed for `aiohttp' called: 1.19s

Streaming

另一个有效的速度优化是流式传输请求。发出请求时,默认情况下会立即下载响应的正文。请求库提供的流参数或aiohttp的content属性都提供了一种在执行请求后不立即将全部内容加载到内存中的方法。

import requests

# Use `with` to make sure the response stream is closed and the connection can
# be returned back to the pool.
with requests.get('http://example.org', stream=True) as r:
print(list(r.iter_content()))

用aiohttp流

import aiohttp
import asyncio
async def get(url):
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
return await response.content.read()
loop = asyncio.get_event_loop()
tasks = [asyncio.ensure_future(get("https://china-testing.github.io/"))]
loop.run_until_complete(asyncio.wait(tasks))
print("Results: %s" % [task.result() for task in tasks])

为了避免无用地分配可能的数百兆内存,不加载全部内容非常重要。如果您的程序不需要整体访问整个内容,而是可以处理块,那么最好使用这些方法。例如,如果您要保存内容并将其写入文件,则仅读取一个块并同时写入它将比读取整个HTTP正文(分配大量的内存)具有更高的内存效率。然后将其写入磁盘。

我希望这可以使您更轻松地编写适当的HTTP客户端和请求。如果您知道任何其他有用的技术或方法,请随时在下面的评论部分写下来!

Python高性能HTTP客户端库requests的使用的更多相关文章

  1. 【Python】 http客户端库requests & urllib2 以及ip地址处理IPy

    requests requests是个HTTPClient库,相比于urllib,urllib2等模块比更加简洁易用 ■ get请求 作为示例,讲一下关于requests如何发起并处理一个get请求 ...

  2. 【网络爬虫入门02】HTTP客户端库Requests的基本原理与基础应用

    [网络爬虫入门02]HTTP客户端库Requests的基本原理与基础应用 广东职业技术学院  欧浩源 1.引言 实现网络爬虫的第一步就是要建立网络连接并向服务器或网页等网络资源发起请求.urllib是 ...

  3. 原!!win7-64 安装python的 redis客户端库

    安装python的redis客户端库 本人系统已装python2.7 利用cmd命令行: 1.cmd-->python -->>>进入python命令下 >>> ...

  4. 【Python爬虫】爬虫利器 requests 库小结

    requests库 Requests 是一个 Python 的 HTTP 客户端库. 支持许多 HTTP 特性,可以非常方便地进行网页请求.网页分析和处理网页资源,拥有许多强大的功能. 本文主要介绍 ...

  5. python第三方库requests详解

    Requests 是用Python语言编写,基于 urllib,采用 Apache2 Licensed 开源协议的 HTTP 库.它比 urllib 更加方便,可以节约我们大量的工作,完全满足 HTT ...

  6. python WEB接口自动化测试之requests库详解

    由于web接口自动化测试需要用到python的第三方库--requests库,运用requests库可以模拟发送http请求,再结合unittest测试框架,就能完成web接口自动化测试. 所以笔者今 ...

  7. (转)Python爬虫利器一之Requests库的用法

    官方文档 以下内容大多来自于官方文档,本文进行了一些修改和总结.要了解更多可以参考 官方文档 安装 利用 pip 安装 $ pip install requests 或者利用 easy_install ...

  8. python第三方库requests简单介绍

    一.发送请求与传递参数 简单demo: import requests r = requests.get(url='http://www.itwhy.org') # 最基本的GET请求 print(r ...

  9. Python爬虫利器一之Requests库的用法

    前言 之前我们用了 urllib 库,这个作为入门的工具还是不错的,对了解一些爬虫的基本理念,掌握爬虫爬取的流程有所帮助.入门之后,我们就需要学习一些更加高级的内容和工具来方便我们的爬取.那么这一节来 ...

随机推荐

  1. requests接口自动化4-登录后才能访问的get请求,需共享cookie

    登录后才能访问的get请求,需共享cookie fiddler里请求响应结果: 代码: import requests import json #form表单形式的post请求,用data传参,Con ...

  2. 消息队列-一篇读懂rabbitmq(生命周期,confirm模式,延迟队列,集群)

    什么是消息队列? 就是生产者生产一条消息,发送到这个rabbitmq,消费者连接rabbitmq并且进行消费,生产者和消费者并需要知道对方是如何工作的,从而实现程序之间的解耦,异步和削峰,这也就是消息 ...

  3. 数据可视化之DAX篇(二)Power BI中的度量值和计算列,你搞清楚了吗?

    https://zhuanlan.zhihu.com/p/75462046 对于初学者,总是会把度量值和计算列搞混,我也经常碰到这样的问题,有些星友用文章中的代码总是报错,发给我一看,才知道TA把本来 ...

  4. Python之爬虫(七)正则的基本使用

    什么是正则表达式 正则表达式是对字符串操作的一种逻辑公式,就是 事先定义好的一些特定字符.及这些特定字符的组合,组成一个“规则字符”,这个“规则字符” 来表达对字符的一种过滤逻辑. 正则并不是pyth ...

  5. bzoj3384[Usaco2004 Nov]Apple Catching 接苹果*&&bzoj1750[Usaco2005 qua]Apple Catching*

    bzoj3384[Usaco2004 Nov]Apple Catching 接苹果 bzoj1750[Usaco2005 qua]Apple Catching 题意: 两棵树,每分钟会从其中一棵树上掉 ...

  6. day6 python while,for 循环控制

    1.1双向循环控制流程 i = 0 while i > 10: #外层循环 j = 10 while j < 0: #内层循环 j -= 1 i += 1 1.1.1 双向循环练习---- ...

  7. 用Tableau制作官网流量周报

    好久没写博客了,上班摸鱼时间分享一下在工作中做的东西吧,先上图. 数据方面取自百度统计,身处传统类型公司,官网没有数据库,只好将就一下啦,反正是免费的,体验也还可以. 关于百度统计注册.添加管理站点和 ...

  8. 由一个计数器出发:关于vue使用独立js文件的问题

    最近有个vue项目要用ztree. 然后,我想把一些逻辑提出来作为公共的方法,放到独立的js文件里. ztreeTool.js import $ from 'jquery' export defaul ...

  9. 通过jmeter读取csv的case来实现接口自动化

    一.环境准备: 1.环境:jdk:1.8+,jmeter:4.2+, 2.csv: 按照以下这种方式编写case或者自定义其他的,准备好case 二.注意要点: 1.想实现数据参数化,可以直接csv中 ...

  10. 高效C++:继承和实现

    如何正确的使用继承和实现是本章说明的重点. 确定public继承的关系是is-a public继承等同于is-a 对public继承,所有base的特性,在derived上都适用 避免遮掩继承而来的名 ...