什么是 httpx?
Scrapeless 代理允许你的 HTTP 客户端通过选定的代理连接来路由出站请求。
HTTPX 是一个具有同步和异步接口的 Python HTTP 客户端。它负责发送请求、管理连接,并提供响应供你的应用程序进行检查。它支持 HTTP/1.1 以及可选的 HTTP/2 操作,因此在需要显式客户端生命周期的脚本、网络服务和数据收集器中非常有用。
该名称也可以指代无关的软件,因此本页主要介绍的是这个 Python 库。它最有用的设计特性是能够在不放弃熟悉的请求概念的前提下选择执行模型。你依然使用方法、URL、头信息和响应主体来工作;异步客户端则改变了应用程序等待这些响应的方式。
在一次 HTTPX 请求期间会发生什么?
HTTPX 请求会将应用程序设置传递给传输层,后者连接到目标并交换 HTTP 消息。结果是一个响应对象,其中包含状态、标头和正文内容等信息。 HTTPX 客户端接口 还支持身份验证、Cookie、流式传输和客户端级别的配置。
在此路径上存在几种截然不同的结果。连接可能在任何 HTTP 响应产生之前就失败。服务器可能返回 HTTP 错误状态。成功的状态也可能携带应用程序无法使用的内容。将这些情况视为独立情形,以便数据管道能够解释实际发生了什么。
调用响应的 JSON 解析器只会对主体进行解码。它不会验证价格是否存在、记录是否属于请求的条目,或分页是否到达预期的终点。应用程序本身负责这些检查。HTTPX 提供用于做出这些决策的传输结果。
同步客户端与异步客户端有何不同?
同步客户端在调用执行路径中等待,而异步客户端则向异步应用程序暴露可被等待的操作。对于简单的顺序工作,请使用同步 Client。当前后端应用程序已经在协调异步操作或需要与其他独立的 I/O 重叠时,请使用 AsyncClient。
异步并不自动意味着并发。一个在开始下一个请求前等待每个请求完成的协程依然是顺序执行的。调度器必须在网络等待期间获得可并行的独立工作,网络等待才能重叠。你的程序还需要对活动操作数量制定一个有上限的策略;仅靠客户端类型本身并不能提供完整的负载策略。
对于一个示例性的文档检查器,如果每个文档都依赖于从前一个文档中提取的值,那么同步循环可能就足够了。当检查器已经拥有相互独立的 URL 时,异步设计更具吸引力。决策应当依据这些依赖关系,而不是对某种语法的偏好。
为什么可复用的客户端很重要
可重用的 HTTPX 客户端在请求之间维护一个连接池和共享配置。重用一个符合条件的连接,可以避免针对同一目标的每个请求都重新建立连接。这样可以减少连接建立的开销,但其收益取决于具体的工作负载以及服务器是否允许重用连接。
将客户端放置在一个连贯的范围内,例如一个批处理或服务组件。在每次迭代中都新建一个客户端,会大大削弱使用连接池的意义。而在其所有者结束后仍将客户端保持打开状态,则会产生相反的问题:资源在没有明确生命周期的情况下继续存活。
客户端级别的请求头和 Cookie 也会在该作用域内保持持久。这对于保持一致的公共数据会话很方便,但需要在不相关的上下文之间进行刻意的隔离。避免在代表不同账户或地区的观测之间共享可变的 Cookie 容器。
连接复用和请求数量是不同的概念。HTTP/2 可以在单个连接上复用多个请求,而 HTTP/1.1 则使用不同的连接行为。不要将最大连接数等同于通用的最大应用操作数。应将应用层限制和传输层连接池设置作为彼此独立的控制项清晰区分和展示。
超时识别不同的等待阶段
HTTPX 区分连接、读取、写入和连接池超时。连接超时与建立连接有关。读取超时与等待传入数据有关。写入超时与发送数据有关,而连接池超时与在客户端中等待可用连接槽位有关。
因此,即使目标端是健康的,连接池超时也可能表明本地争用。对于从不关闭其流或其工作负载超出自身连接配额的客户端,仅仅增加远端容量并不能解决问题。记录带有受影响操作的异常类别,这样诊断就能从正确的层级开始。
不应将每个阶段的超时误认为是涵盖整个业务任务的统一截止时间。作业在调用 HTTPX 之前可能会在应用程序队列中等待,并且在请求结束后可能还会解析或存储数据。如果任务有一个总的截止时间,应单独跟踪该时间。
根据应用程序合约和观测到的工作负载选择超时值。小的元数据响应和大的允许下载有不同的需求。移除所有限制可能会让资源无限期地被占用;将每个限制都设得极短又可能会拒绝本可满足任务要求的工作。
如何正确验证回复
响应验证按顺序检查传输成功、HTTP 含义和应用程序内容。 HTTP 语义标准 定义了方法和状态含义,但成功状态并不代表你的抽取逻辑是正确的。一个有效响应仍然可能描述与你任务不符的资源。
从请求的 URL 和最终 URL 开始。如果启用了重定向跟随,先检查客户端最终到达的位置。然后在解码响应体之前检查媒体类型。解码后,验证预期字段及其类型。为每个被拒绝的响应保留原因,以免空数据集被静默地当成积极的业务结果。
例如,一个产品观测可能需要产品标识符和货币单位以及价格。如果价格存在但缺少货币单位,应用程序就不应在缺乏进一步上下文的情况下,把该数值合并进跨市场比较。这是一个数据模型规则,与客户端库无关。
将缺失值与空集合和显式的零值区分开来。缺少库存字段并不能证明库存为零。仅当周围的响应内容确认查询已被接受并完成时,才可以将没有任何条目的 JSON 数组视为合法结果。
流式处理需要显式的生命周期
流式处理允许应用程序增量消费响应,而不必在处理前加载整个响应体。这对大文件或数据流很有用,但也带来了资源义务:必须根据客户端接口消费或关闭流。
使用上下文管理的流可以为这种义务划定清晰边界。如果验证较早失败,离开上下文仍应关闭流。保持部分消费的响应处于打开状态会耗尽连接池,使无关请求因为资源“莫名其妙地不可用”而被迫等待。
增量输入也会改变解析器设计。分块边界是一个传输边界,不一定对应完整的 JSON 对象、文本字符或应用记录。使用适合该格式的解析器,并在下一块数据到达前保留不完整数据。不要假设一块数据就等于一条有意义的记录。
代理路由和证书验证
代理会通过中间方路由 HTTPX 流量,而 TLS 验证会对客户端预期的安全端点进行身份验证。这些控制解决的是不同的问题。成功建立代理连接并不能成为禁用证书检查的理由,而已验证的证书也不能说明选择了哪个地理出口。
该 TLS 安全协议 提供 HTTPS 使用的加密传输。在通过 HTTP 代理建立的传统 HTTPS 隧道中,客户端可以通过该隧道对目标建立 TLS 连接。显式配置的检测代理则有不同的信任模型,应按这种情况单独评估。
使用当前的 Scrapeless proxy setup 获取正确的连接详情。将代理凭据保存在版本控制之外,并在日志中编辑掉包含认证信息的完整代理 URL。相关的 HTTPX and Scrapeless Proxies walkthrough 是有用的背景资料,但历史示例应与当前产品设置加以对照。
Scrapeless Proxy Solutions 为那些仍保留对请求和解析控制权的应用程序提供网络组件。在承诺执行更大批量任务之前,将所选产品的行为与 current pricing 和批处理需求进行比较。
HTTPX 不会做什么
HTTPX 不会执行页面 JavaScript,也不会渲染浏览器界面。如果响应包含应用外壳,HTTPX 返回的就是该外壳。当所需内容只在浏览器执行或交互之后才存在时,应用需要采用其他采集方式。
HTTPX 也不会像浏览器那样自动缓存每个响应。HTTP 缓存有自己关于存储、新鲜度和验证的规则,这些规则定义在 HTTP caching specification中。将任何应用级缓存视作一个独立组件,并为其设计明确的键和新鲜度策略。
最后,更换客户端并不能自动获得访问资源的权限。请使用符合工作流的、已文档化的接口和允许访问的页面。即使另一个客户端返回了不同响应,身份验证要求仍然是边界。
结论
HTTPX 为 Python 应用提供了在同步和异步 HTTP 操作之间清晰的选择。在受控作用域内复用客户端,按阶段区分超时,并关闭响应流。只有在根据任务验证返回内容之后才接受数据,而不是把 HTTP 状态当作最终结果。
构建一个 HTTPX 采集工作流
让可复用 HTTP 客户端与所需的代理位置、连接生命周期以及数据检查策略相匹配。
立即注册即可获得 $5 in free credit — 无需信用卡.
领取你的 $5 额度 →FAQ
HTTPX 仅适用于异步 Python 吗?
HTTPX 同时支持同步和异步的 Python 应用。根据周围的执行模型以及请求之间的依赖关系,选择 Client 或 AsyncClient。
HTTPX 会自动支持 HTTP/2 吗?
HTTPX 通过其可选依赖和配置支持 HTTP/2。启用客户端对 HTTP/2 的支持并不保证每个目标都会协商使用 HTTP/2。
池超时是什么意思?
池超时表示客户端在配置的等待时间内未能获取连接。在认为是目标站点导致延迟之前,请先检查连接数限制、未完成操作以及未关闭的流。
HTTPX 能渲染 JavaScript 页面吗?
HTTPX 无法像浏览器那样渲染 JavaScript 页面。它获取的是 HTTP 内容,该内容可能包含脚本或一个空的应用外壳,而不是最终渲染的数据。
是否应为每个请求都创建一个客户端?
对于相关请求,通常应复用客户端,因为这样可以保留连接池和共享配置。当存在不同生命周期或需要隔离会话上下文时,再创建单独的客户端。