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. js代码段

    1.数组去重 Array.prototype.DuplicateRemoval = function(){ let res = [this[0]]; for(let i = 1; i < thi ...

  2. Unity-JobSystem

    NativeContainer 为什么 为解决Job之间数据处理结果的隔离问题. 是什么 NativeContainer是托管的值类型,可以相对安全的操作native内存. 注意 不能两个job同时写 ...

  3. bzoj2648SJY摆棋子&&bzoj2716[Violet 3]天使玩偶*

    bzoj2648SJY摆棋子 bzoj2716[Violet 3]天使玩偶 题意: 棋盘上有n个棋子,现在有m个操作,一种是加棋子,一种是查询离某个点最近的棋子.n,m≤500000. 题解: 先将已 ...

  4. Java常用API(Scanner类)

    Java常用API( Scanner类)1 1.Scanner类 首先给大家介绍一下什么是JavaAPI API(Application Programming Interface),应用程序编程接口 ...

  5. 洛谷 P5022 旅行

    今天换标题格式了,因为感觉原版实在有点别扭…… 还是直接上题板,看完题再讲吧: 对了有个小细节没说,m一定是等于n或者等于n-1的. 这题是2018年提高组的真题哦!被我肝了2天肝出来了,2天……(真 ...

  6. Vue全家桶之一Vue(基础知识篇)

    全家桶:Vue本身.状态管理.路由.   异步组件:     

  7. STL源码剖析:迭代器

    准备知识 什么是迭代器? 迭代器是链接容器和算法的桥梁,所有的算法都通过迭代器操作容器中的数据 迭代器是一种智能指针,最重要的操作符重载就是operator*,operator-> 迭代器的实现 ...

  8. 多云架构下,JAVA微服务技术选型实例解析

    [摘要] 本文介绍了基于开源自建和适配云厂商开发框架两种构建多云架构的思路,以及这些思路的优缺点. 微服务生态 微服务生态本质上是一种微服务架构模式的实现,包括微服务开发SDK,以及微服务基础设施. ...

  9. 抓取Android崩溃日志

    作为一个测试人员,特别是安卓的测试,由于系统版本的不同和手机本身各个品牌的优化和硬件的不同,会出现各种各样的崩溃. 记录崩溃的方式有很多种,比如使用录屏工具或文档进行记录,但是最简洁明了可以直接定位的 ...

  10. C# 13位时间戳(unix时间戳)

    1.转义字符用在中间. "\"' 2.C#获取13位时间戳(unix时间戳) /// <summary>   /// 将c# DateTime时间格式转换为Unix时间 ...