Skip to main content

hs-net

统一多引擎的增强型 HTTP 客户端,内置重试、选择器、信号中间件,同步异步全支持。

特性

  • 多引擎切换 — httpx、aiohttp、curl-cffi、requests、requests-go,统一 API,一行切换
  • 同步 & 异步Net(异步)和 SyncNet(同步),接口完全一致
  • 智能选择器 — 内置 CSS、XPath、正则、JMESPath 四种数据提取(可选安装)
  • 流式响应 — 支持分块下载大文件,所有引擎统一接口
  • 自动重试 — 基于 tenacity,可配置次数、间隔、随机抖动
  • 信号中间件 — 请求前、响应后、重试时三个钩子
  • 统一异常 — 超时、连接失败、状态码错误等统一映射,切换引擎不影响错误处理
  • 反爬支持 — curl-cffi 浏览器 TLS 指纹模拟 + 内置真实 User-Agent 池(浏览器 / 搜索引擎爬虫 / 微信)
  • 轻量核心 — 核心仅依赖 httpx + tenacity,爬虫增强按需安装

安装

# 核心安装(默认 httpx 引擎,仅 2 个依赖)
pip install hs-net

# 爬虫增强(CSS/XPath 选择器 + JMESPath + 速率限制)
pip install hs-net[sp]

# 按需安装额外引擎
pip install hs-net[aiohttp]      # aiohttp 引擎
pip install hs-net[curl]         # curl-cffi 引擎(浏览器指纹模拟)
pip install hs-net[requests]     # requests 引擎
pip install hs-net[requests-go]  # requests-go 引擎
pip install hs-net[all]          # 全部引擎 + 爬虫增强

Python >= 3.10。默认安装仅包含 httpx + tenacity,选择器需安装 [sp]。User-Agent 池是内置的,无需额外依赖。

快速开始

异步

import asyncio
from hs_net import Net

async def main():
    async with Net() as net:
        resp = await net.get("https://example.com")
        print(resp.text)         # 纯 HTTP 客户端,无需额外依赖
        print(resp.json_data)    # JSON 响应自动解析

asyncio.run(main())

同步

from hs_net import SyncNet

with SyncNet() as net:
    resp = net.get("https://example.com")
    print(resp.status_code)  # 200
    print(resp.text[:100])   # 响应文本

数据提取(需要 pip install hs-net[sp]

with SyncNet() as net:
    resp = net.get("https://example.com")
    resp.css("title::text").get()               # CSS 选择器
    resp.xpath("//h1/text()").get()             # XPath
    resp.re_first(r"价格: (\d+)元")             # 正则

    resp = net.get("https://api.example.com")
    resp.jmespath("data[?age > `18`].name")     # JMESPath(JSON)

引擎对比

特性 httpx aiohttp curl-cffi requests requests-go
异步支持
同步支持
HTTP/2
TLS 指纹模拟
SOCKS 代理
安装方式 默认 [aiohttp] [curl] [requests] [requests-go]
推荐场景 通用首选 高并发 反爬 兼容老项目 反爬+性能

引擎切换

# httpx(默认)
Net(engine="httpx")

# aiohttp
Net(engine="aiohttp")

# curl-cffi(支持浏览器指纹模拟)
Net(engine="curl_cffi", engine_options={"impersonate": "chrome"})

# requests(仅同步)
SyncNet(engine="requests")

# requests-go
Net(engine="requests_go")

快捷函数(无需实例化)

import hs_net

# 异步
resp = await hs_net.get("https://example.com")
resp = await hs_net.post("https://api.example.com/data", json_data={"key": "val"})

# 同步
resp = hs_net.sync_get("https://example.com")

# 指定引擎
resp = await hs_net.get("https://example.com", engine="curl_cffi")

快捷函数每次创建临时客户端,适合简单请求。需要复用连接、配置中间件时请使用 Net / SyncNet

流式响应

分块下载大文件,不占内存:

# 异步
async with Net() as net:
    resp = await net.stream("GET", "https://example.com/large-file.zip")
    async with resp:
        async for chunk in resp:
            f.write(chunk)

# 同步
with SyncNet() as net:
    with net.stream("GET", "https://example.com/large-file.zip") as resp:
        for chunk in resp:
            f.write(chunk)

配置

from hs_net import Net, NetConfig

# 方式 1:构造函数参数
net = Net(
    engine="httpx",
    base_url="https://api.example.com/v1",
    timeout=30.0,
    retries=5,
    retry_delay=1.0,
    user_agent="chrome",
    proxy="http://127.0.0.1:7890",
    verify=False,
    raise_status=True,
    allow_redirects=True,
    concurrency=10,
    headers={"Accept-Language": "zh-CN"},
    cookies={"token": "abc123"},
    engine_options={"http2": True},
)

# 方式 2:NetConfig 对象
config = NetConfig(
    engine="curl_cffi",
    retries=3,
    user_agent="random",
    headers={"Authorization": "Bearer token"},
    engine_options={"impersonate": "chrome"},
)
net = Net(config=config)

每次请求也可以覆盖全局配置:

async with Net(timeout=10, retries=3) as net:
    # 这次请求用不同的超时、代理、UA
    resp = await net.get(
        "https://example.com",
        params={"q": "python"},
        timeout=30.0,
        proxy="http://127.0.0.1:7890",
        user_agent="MyBot/1.0",
        headers={"X-Custom": "value"},
        cookies={"session": "xyz"},
        verify=False,
        retries=5,
        retry_delay=1.0,
        raise_status=False,
        allow_redirects=True,
    )

    # POST 还支持 json_data / form_data / files
    resp = await net.post(
        "https://api.example.com/upload",
        json_data={"key": "value"},
        # form_data={"field": "value"},
        # files={"file": ("name.txt", b"content", "text/plain")},
    )

参数优先级:请求方法参数 > 构造函数参数 > NetConfig 默认值

User-Agent

默认就是当前版本的桌面 Chrome,不用配置。要换用内置的真实 UA 池,传快捷方式即可(不区分大小写):

Net(user_agent="random")       # 任意桌面浏览器
Net(user_agent="chrome")       # 指定浏览器:chrome / firefox / edge / safari
Net(user_agent="mobile")       # 任意移动端浏览器
Net(user_agent="android")      # 指定平台:android / ios
Net(user_agent="bot")          # 任意搜索引擎爬虫
Net(user_agent="baiduspider")  # 指定爬虫,见下表
Net(user_agent="wechat")       # 微信内置浏览器
Net(user_agent="MyBot/1.0")    # 完整字符串则原样使用
类别 快捷方式
桌面浏览器 randomchromefirefoxff)、edgesafari
移动端浏览器 mobileandroidiosiphone
搜索引擎爬虫 botgooglebotgoogle)、bingbotbing)、baiduspiderbaidu)、sogou360spiderbytespiderbytedance/toutiao)、yandexbotyandex)、duckduckbotapplebot
App 内置浏览器 wechatweixin/micromessenger

randommobile 是桌面、移动端各自的随机入口。爬虫和微信有特定用途,需要显式指定,不会被随机取到。不在上表中的字符串一律当作自定义 UA 使用。

from hs_net import DEFAULT_USER_AGENT, user_agent_shortcuts

DEFAULT_USER_AGENT      # 当前默认 UA
user_agent_shortcuts()  # 列出全部快捷方式(含别名)

UA 数据内置在包里(约 13 KB,无额外依赖),由 scripts/gen_ua_data.py 从四个上游源合并生成:

来源 提供
jnrbsn/user-agents 各浏览器最新版本,日更
microlinkhq/top-user-agents 真实流量最常用的 100 条,日更
monperrus/crawler-user-agents 搜索引擎爬虫,含中文生态
App Store lookup API 微信当前版本号

信号中间件

async with Net() as net:

    @net.on_request_before
    async def add_auth(req_data):
        req_data.headers["Authorization"] = "Bearer token"
        return req_data

    @net.on_response_after
    async def log_response(resp):
        print(f"{resp.status_code} {resp.url}")

    @net.on_request_retry
    async def on_retry(exc):
        print(f"重试: {exc}")

    resp = await net.get("https://example.com")

错误处理

所有引擎的异常统一映射,切换引擎不影响错误处理代码:

from hs_net import (
    Net, StatusException, TimeoutException,
    ConnectionException, RetryExhausted, RequestException,
)

async with Net() as net:
    try:
        resp = await net.get("https://httpbin.org/status/404")
    except TimeoutException as e:
        print(f"超时: timeout={e.timeout}s")
    except ConnectionException as e:
        print(f"连接失败: {e.url}")
    except RetryExhausted as e:
        print(f"{e.attempts} 次重试失败: {e.last_exception}")
    except StatusException as e:
        print(f"HTTP {e.code}")
    except RequestException as e:
        print(f"请求异常: {e}")

文档

完整文档见 docs/ 目录,本地预览:

cd docs
pnpm install
pnpm run dev

License

MIT

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

hs_net-0.4.0.tar.gz (405.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

hs_net-0.4.0-py3-none-any.whl (57.6 kB view details)

Uploaded Python 3

File details

Details for the file hs_net-0.4.0.tar.gz.

File metadata

  • Download URL: hs_net-0.4.0.tar.gz
  • Upload date:
  • Size: 405.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for hs_net-0.4.0.tar.gz
Algorithm Hash digest
SHA256 728a644dddca72b9e625c08257e1d01ebae6e4c63733b70f783163c398492099
MD5 7c4126a8c0a0b0c16c3e1a0f56d32a9f
BLAKE2b-256 541907ea517ad3408dfd49223a6d64f0150745e7d289f4d2c258931f441a59ee

See more details on using hashes here.

File details

Details for the file hs_net-0.4.0-py3-none-any.whl.

File metadata

  • Download URL: hs_net-0.4.0-py3-none-any.whl
  • Upload date:
  • Size: 57.6 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.12.3 {"installer":{"name":"uv","version":"0.12.3","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for hs_net-0.4.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5695e8065aa7fbdc62356ad12807ff4e576b05747a1d9fc5312550df813404d2
MD5 f2016982734c53e355c8d2d16eda50b6
BLAKE2b-256 6d23f3c6ef1dca23d73ac6880612663447dd4a2963f5aec862596510404ee373

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.4.0 This release

2 files

0.3.3

2 files

0.3.2

2 files

0.3.1

2 files

0.3.0

2 files

0.2.0

2 files

0.1.0

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page