reqkeeper


Namereqkeeper JSON
Version 1.0.0 PyPI version JSON
download
home_pagehttps://github.com/Flikify/reqkeeper
Summary一个功能强大的HTTP会话持久化工具
upload_time2025-08-12 03:13:02
maintainerNone
docs_urlNone
authorFlikify
requires_python>=3.7
licenseMIT
keywords http requests session persistent cookies retry interceptor
VCS
bugtrack_url
requirements requests tenacity urllib3
Travis-CI No Travis.
coveralls test coverage No coveralls.
            # Requests-Keeper

一个功能强大的HTTP会话持久化工具,支持会话保存、自动重试、请求拦截器等功能。

## 特性

- 🔄 **会话持久化** - 自动保存和恢复HTTP会话,包括cookies、headers等
- ⚡ **自动重试** - 内置智能重试机制,处理网络波动和服务器错误
- 🎯 **拦截器系统** - 支持请求和响应拦截器,方便添加认证、日志等功能
- 📝 **便捷的JSON API** - 提供get_json、post_json等便捷方法
- 🛡️ **错误处理** - 完善的错误处理和日志记录
- ⏱️ **频率限制** - 内置请求频率控制
- 🔧 **高度可配置** - 支持自定义超时、重试策略等

## 安装

```bash
pip install reqkeeper
```

## 快速开始

### 基本使用

```python
from reqkeeper import PersistentSession

# 创建持久化会话
with PersistentSession() as session:
    # GET请求
    response = session.get('https://httpbin.org/get')
    print(response.json())
    
    # POST请求
    data = session.post_json('https://httpbin.org/post', json={'key': 'value'})
    print(data)
    
    # 会话会自动保存cookies等信息
```

### 添加拦截器

```python
from reqkeeper import PersistentSession, auth_interceptor, logging_request_interceptor

with PersistentSession() as session:
    # 添加认证拦截器
    session.add_request_interceptor(auth_interceptor("your_token_here"))
    
    # 添加日志拦截器
    session.add_request_interceptor(logging_request_interceptor)
    
    # 现在所有请求都会自动添加认证头和日志
    response = session.get('https://api.example.com/protected')
```

### 自定义配置

```python
from reqkeeper import PersistentSession

session = PersistentSession(
    session_file='./my_session.pkl',  # 自定义会话文件位置
    retries=5,                        # 重试次数
    timeout=60,                       # 请求超时
    auto_save=True                    # 自动保存会话
)
```

## 内置拦截器

### 认证拦截器
```python
from reqkeeper import auth_interceptor

# Bearer token
auth = auth_interceptor("your_token_here")
session.add_request_interceptor(auth)

# API Key
api_auth = auth_interceptor("your_api_key", auth_type="ApiKey")
session.add_request_interceptor(api_auth)
```

### 日志拦截器
```python
from reqkeeper import logging_request_interceptor, logging_response_interceptor

session.add_request_interceptor(logging_request_interceptor)
session.add_response_interceptor(logging_response_interceptor)
```

### 频率限制拦截器
```python
from reqkeeper import rate_limit_interceptor

# 每秒最多2个请求
rate_limiter = rate_limit_interceptor(2.0)
session.add_request_interceptor(rate_limiter)
```

### 错误处理拦截器
```python
from reqkeeper import error_handling_interceptor

session.add_response_interceptor(error_handling_interceptor)
```

## 完整示例

```python
import logging
from reqkeeper import (
    PersistentSession,
    auth_interceptor,
    logging_request_interceptor,
    logging_response_interceptor,
    error_handling_interceptor,
    rate_limit_interceptor
)

# 配置日志
logging.basicConfig(level=logging.INFO)

def main():
    with PersistentSession(
        session_file='./api_session.pkl',
        retries=3,
        timeout=30,
        auto_save=True
    ) as session:
        
        # 添加各种拦截器
        session.add_request_interceptor(logging_request_interceptor)
        session.add_request_interceptor(rate_limit_interceptor(2.0))  # 每秒2个请求
        
        session.add_response_interceptor(logging_response_interceptor)
        session.add_response_interceptor(error_handling_interceptor)
        
        # 如果需要认证
        # session.add_request_interceptor(auth_interceptor("your_token"))
        
        try:
            # API调用
            user_data = session.get_json('https://api.example.com/user/profile')
            print(f"用户数据: {user_data}")
            
            # 提交数据
            result = session.post_json(
                'https://api.example.com/data',
                json={'message': 'Hello from persistent-requests!'}
            )
            print(f"提交结果: {result}")
            
            print(f"会话保存在: {session.get_session_file_path()}")
            
        except Exception as e:
            print(f"请求失败: {e}")

if __name__ == "__main__":
    main()
```

## API参考

### Reqkeeper

主要的会话类,提供持久化HTTP请求功能。

#### 构造函数

```python
reqkeeper(
    session_file: Optional[str] = None,
    retries: int = 3,
    backoff_factor: float = 0.3,
    timeout: int = 30,
    auto_save: bool = True
)
```

- `session_file`: 会话保存文件路径,默认为系统临时目录
- `retries`: 失败重试次数
- `backoff_factor`: 重试延迟倍数
- `timeout`: 请求超时时间(秒)
- `auto_save`: 是否在每次请求后自动保存会话

#### 请求方法

- `get(url, params=None, **kwargs)` - GET请求
- `post(url, data=None, json=None, **kwargs)` - POST请求
- `put(url, data=None, json=None, **kwargs)` - PUT请求
- `patch(url, data=None, json=None, **kwargs)` - PATCH请求
- `delete(url, **kwargs)` - DELETE请求
- `head(url, **kwargs)` - HEAD请求
- `options(url, **kwargs)` - OPTIONS请求
- `request(method, url, **kwargs)` - 通用请求方法

#### JSON便捷方法

- `get_json(url, params=None, **kwargs)` - GET请求并返回JSON
- `post_json(url, data=None, json=None, **kwargs)` - POST请求并返回JSON
- `request_json(method, url, **kwargs)` - 通用请求并返回JSON

#### 拦截器管理

- `add_request_interceptor(interceptor)` - 添加请求拦截器
- `add_response_interceptor(interceptor)` - 添加响应拦截器
- `remove_request_interceptor(interceptor)` - 移除请求拦截器
- `remove_response_interceptor(interceptor)` - 移除响应拦截器
- `clear_interceptors()` - 清除所有拦截器

#### 会话管理

- `save_session()` - 手动保存会话
- `get_session_file_path()` - 获取会话文件路径
- `close()` - 关闭会话

## 许可证

MIT License

## 更新日志

### v1.0.0

- 初始版本发布
- 支持会话持久化
- 内置重试机制
- 拦截器系统
- JSON便捷方法
- 完善的错误处理

## 贡献

欢迎提交Issue和Pull Request!

## 作者

Flikify - reqkeeper@92coco.cn

项目链接: https://github.com/Flikify/reqkeeper

            

Raw data

            {
    "_id": null,
    "home_page": "https://github.com/Flikify/reqkeeper",
    "name": "reqkeeper",
    "maintainer": null,
    "docs_url": null,
    "requires_python": ">=3.7",
    "maintainer_email": null,
    "keywords": "http, requests, session, persistent, cookies, retry, interceptor",
    "author": "Flikify",
    "author_email": "Flikify <reqkeeper@92coco.cn>",
    "download_url": "https://files.pythonhosted.org/packages/d0/46/aac0808424ea440920ce6528c0906cc5342509b30ccc90a8156d283f8c54/reqkeeper-1.0.0.tar.gz",
    "platform": null,
    "description": "# Requests-Keeper\n\n\u4e00\u4e2a\u529f\u80fd\u5f3a\u5927\u7684HTTP\u4f1a\u8bdd\u6301\u4e45\u5316\u5de5\u5177\uff0c\u652f\u6301\u4f1a\u8bdd\u4fdd\u5b58\u3001\u81ea\u52a8\u91cd\u8bd5\u3001\u8bf7\u6c42\u62e6\u622a\u5668\u7b49\u529f\u80fd\u3002\n\n## \u7279\u6027\n\n- \ud83d\udd04 **\u4f1a\u8bdd\u6301\u4e45\u5316** - \u81ea\u52a8\u4fdd\u5b58\u548c\u6062\u590dHTTP\u4f1a\u8bdd\uff0c\u5305\u62eccookies\u3001headers\u7b49\n- \u26a1 **\u81ea\u52a8\u91cd\u8bd5** - \u5185\u7f6e\u667a\u80fd\u91cd\u8bd5\u673a\u5236\uff0c\u5904\u7406\u7f51\u7edc\u6ce2\u52a8\u548c\u670d\u52a1\u5668\u9519\u8bef\n- \ud83c\udfaf **\u62e6\u622a\u5668\u7cfb\u7edf** - \u652f\u6301\u8bf7\u6c42\u548c\u54cd\u5e94\u62e6\u622a\u5668\uff0c\u65b9\u4fbf\u6dfb\u52a0\u8ba4\u8bc1\u3001\u65e5\u5fd7\u7b49\u529f\u80fd\n- \ud83d\udcdd **\u4fbf\u6377\u7684JSON API** - \u63d0\u4f9bget_json\u3001post_json\u7b49\u4fbf\u6377\u65b9\u6cd5\n- \ud83d\udee1\ufe0f **\u9519\u8bef\u5904\u7406** - \u5b8c\u5584\u7684\u9519\u8bef\u5904\u7406\u548c\u65e5\u5fd7\u8bb0\u5f55\n- \u23f1\ufe0f **\u9891\u7387\u9650\u5236** - \u5185\u7f6e\u8bf7\u6c42\u9891\u7387\u63a7\u5236\n- \ud83d\udd27 **\u9ad8\u5ea6\u53ef\u914d\u7f6e** - \u652f\u6301\u81ea\u5b9a\u4e49\u8d85\u65f6\u3001\u91cd\u8bd5\u7b56\u7565\u7b49\n\n## \u5b89\u88c5\n\n```bash\npip install reqkeeper\n```\n\n## \u5feb\u901f\u5f00\u59cb\n\n### \u57fa\u672c\u4f7f\u7528\n\n```python\nfrom reqkeeper import PersistentSession\n\n# \u521b\u5efa\u6301\u4e45\u5316\u4f1a\u8bdd\nwith PersistentSession() as session:\n    # GET\u8bf7\u6c42\n    response = session.get('https://httpbin.org/get')\n    print(response.json())\n    \n    # POST\u8bf7\u6c42\n    data = session.post_json('https://httpbin.org/post', json={'key': 'value'})\n    print(data)\n    \n    # \u4f1a\u8bdd\u4f1a\u81ea\u52a8\u4fdd\u5b58cookies\u7b49\u4fe1\u606f\n```\n\n### \u6dfb\u52a0\u62e6\u622a\u5668\n\n```python\nfrom reqkeeper import PersistentSession, auth_interceptor, logging_request_interceptor\n\nwith PersistentSession() as session:\n    # \u6dfb\u52a0\u8ba4\u8bc1\u62e6\u622a\u5668\n    session.add_request_interceptor(auth_interceptor(\"your_token_here\"))\n    \n    # \u6dfb\u52a0\u65e5\u5fd7\u62e6\u622a\u5668\n    session.add_request_interceptor(logging_request_interceptor)\n    \n    # \u73b0\u5728\u6240\u6709\u8bf7\u6c42\u90fd\u4f1a\u81ea\u52a8\u6dfb\u52a0\u8ba4\u8bc1\u5934\u548c\u65e5\u5fd7\n    response = session.get('https://api.example.com/protected')\n```\n\n### \u81ea\u5b9a\u4e49\u914d\u7f6e\n\n```python\nfrom reqkeeper import PersistentSession\n\nsession = PersistentSession(\n    session_file='./my_session.pkl',  # \u81ea\u5b9a\u4e49\u4f1a\u8bdd\u6587\u4ef6\u4f4d\u7f6e\n    retries=5,                        # \u91cd\u8bd5\u6b21\u6570\n    timeout=60,                       # \u8bf7\u6c42\u8d85\u65f6\n    auto_save=True                    # \u81ea\u52a8\u4fdd\u5b58\u4f1a\u8bdd\n)\n```\n\n## \u5185\u7f6e\u62e6\u622a\u5668\n\n### \u8ba4\u8bc1\u62e6\u622a\u5668\n```python\nfrom reqkeeper import auth_interceptor\n\n# Bearer token\nauth = auth_interceptor(\"your_token_here\")\nsession.add_request_interceptor(auth)\n\n# API Key\napi_auth = auth_interceptor(\"your_api_key\", auth_type=\"ApiKey\")\nsession.add_request_interceptor(api_auth)\n```\n\n### \u65e5\u5fd7\u62e6\u622a\u5668\n```python\nfrom reqkeeper import logging_request_interceptor, logging_response_interceptor\n\nsession.add_request_interceptor(logging_request_interceptor)\nsession.add_response_interceptor(logging_response_interceptor)\n```\n\n### \u9891\u7387\u9650\u5236\u62e6\u622a\u5668\n```python\nfrom reqkeeper import rate_limit_interceptor\n\n# \u6bcf\u79d2\u6700\u591a2\u4e2a\u8bf7\u6c42\nrate_limiter = rate_limit_interceptor(2.0)\nsession.add_request_interceptor(rate_limiter)\n```\n\n### \u9519\u8bef\u5904\u7406\u62e6\u622a\u5668\n```python\nfrom reqkeeper import error_handling_interceptor\n\nsession.add_response_interceptor(error_handling_interceptor)\n```\n\n## \u5b8c\u6574\u793a\u4f8b\n\n```python\nimport logging\nfrom reqkeeper import (\n    PersistentSession,\n    auth_interceptor,\n    logging_request_interceptor,\n    logging_response_interceptor,\n    error_handling_interceptor,\n    rate_limit_interceptor\n)\n\n# \u914d\u7f6e\u65e5\u5fd7\nlogging.basicConfig(level=logging.INFO)\n\ndef main():\n    with PersistentSession(\n        session_file='./api_session.pkl',\n        retries=3,\n        timeout=30,\n        auto_save=True\n    ) as session:\n        \n        # \u6dfb\u52a0\u5404\u79cd\u62e6\u622a\u5668\n        session.add_request_interceptor(logging_request_interceptor)\n        session.add_request_interceptor(rate_limit_interceptor(2.0))  # \u6bcf\u79d22\u4e2a\u8bf7\u6c42\n        \n        session.add_response_interceptor(logging_response_interceptor)\n        session.add_response_interceptor(error_handling_interceptor)\n        \n        # \u5982\u679c\u9700\u8981\u8ba4\u8bc1\n        # session.add_request_interceptor(auth_interceptor(\"your_token\"))\n        \n        try:\n            # API\u8c03\u7528\n            user_data = session.get_json('https://api.example.com/user/profile')\n            print(f\"\u7528\u6237\u6570\u636e: {user_data}\")\n            \n            # \u63d0\u4ea4\u6570\u636e\n            result = session.post_json(\n                'https://api.example.com/data',\n                json={'message': 'Hello from persistent-requests!'}\n            )\n            print(f\"\u63d0\u4ea4\u7ed3\u679c: {result}\")\n            \n            print(f\"\u4f1a\u8bdd\u4fdd\u5b58\u5728: {session.get_session_file_path()}\")\n            \n        except Exception as e:\n            print(f\"\u8bf7\u6c42\u5931\u8d25: {e}\")\n\nif __name__ == \"__main__\":\n    main()\n```\n\n## API\u53c2\u8003\n\n### Reqkeeper\n\n\u4e3b\u8981\u7684\u4f1a\u8bdd\u7c7b\uff0c\u63d0\u4f9b\u6301\u4e45\u5316HTTP\u8bf7\u6c42\u529f\u80fd\u3002\n\n#### \u6784\u9020\u51fd\u6570\n\n```python\nreqkeeper(\n    session_file: Optional[str] = None,\n    retries: int = 3,\n    backoff_factor: float = 0.3,\n    timeout: int = 30,\n    auto_save: bool = True\n)\n```\n\n- `session_file`: \u4f1a\u8bdd\u4fdd\u5b58\u6587\u4ef6\u8def\u5f84\uff0c\u9ed8\u8ba4\u4e3a\u7cfb\u7edf\u4e34\u65f6\u76ee\u5f55\n- `retries`: \u5931\u8d25\u91cd\u8bd5\u6b21\u6570\n- `backoff_factor`: \u91cd\u8bd5\u5ef6\u8fdf\u500d\u6570\n- `timeout`: \u8bf7\u6c42\u8d85\u65f6\u65f6\u95f4\uff08\u79d2\uff09\n- `auto_save`: \u662f\u5426\u5728\u6bcf\u6b21\u8bf7\u6c42\u540e\u81ea\u52a8\u4fdd\u5b58\u4f1a\u8bdd\n\n#### \u8bf7\u6c42\u65b9\u6cd5\n\n- `get(url, params=None, **kwargs)` - GET\u8bf7\u6c42\n- `post(url, data=None, json=None, **kwargs)` - POST\u8bf7\u6c42\n- `put(url, data=None, json=None, **kwargs)` - PUT\u8bf7\u6c42\n- `patch(url, data=None, json=None, **kwargs)` - PATCH\u8bf7\u6c42\n- `delete(url, **kwargs)` - DELETE\u8bf7\u6c42\n- `head(url, **kwargs)` - HEAD\u8bf7\u6c42\n- `options(url, **kwargs)` - OPTIONS\u8bf7\u6c42\n- `request(method, url, **kwargs)` - \u901a\u7528\u8bf7\u6c42\u65b9\u6cd5\n\n#### JSON\u4fbf\u6377\u65b9\u6cd5\n\n- `get_json(url, params=None, **kwargs)` - GET\u8bf7\u6c42\u5e76\u8fd4\u56deJSON\n- `post_json(url, data=None, json=None, **kwargs)` - POST\u8bf7\u6c42\u5e76\u8fd4\u56deJSON\n- `request_json(method, url, **kwargs)` - \u901a\u7528\u8bf7\u6c42\u5e76\u8fd4\u56deJSON\n\n#### \u62e6\u622a\u5668\u7ba1\u7406\n\n- `add_request_interceptor(interceptor)` - \u6dfb\u52a0\u8bf7\u6c42\u62e6\u622a\u5668\n- `add_response_interceptor(interceptor)` - \u6dfb\u52a0\u54cd\u5e94\u62e6\u622a\u5668\n- `remove_request_interceptor(interceptor)` - \u79fb\u9664\u8bf7\u6c42\u62e6\u622a\u5668\n- `remove_response_interceptor(interceptor)` - \u79fb\u9664\u54cd\u5e94\u62e6\u622a\u5668\n- `clear_interceptors()` - \u6e05\u9664\u6240\u6709\u62e6\u622a\u5668\n\n#### \u4f1a\u8bdd\u7ba1\u7406\n\n- `save_session()` - \u624b\u52a8\u4fdd\u5b58\u4f1a\u8bdd\n- `get_session_file_path()` - \u83b7\u53d6\u4f1a\u8bdd\u6587\u4ef6\u8def\u5f84\n- `close()` - \u5173\u95ed\u4f1a\u8bdd\n\n## \u8bb8\u53ef\u8bc1\n\nMIT License\n\n## \u66f4\u65b0\u65e5\u5fd7\n\n### v1.0.0\n\n- \u521d\u59cb\u7248\u672c\u53d1\u5e03\n- \u652f\u6301\u4f1a\u8bdd\u6301\u4e45\u5316\n- \u5185\u7f6e\u91cd\u8bd5\u673a\u5236\n- \u62e6\u622a\u5668\u7cfb\u7edf\n- JSON\u4fbf\u6377\u65b9\u6cd5\n- \u5b8c\u5584\u7684\u9519\u8bef\u5904\u7406\n\n## \u8d21\u732e\n\n\u6b22\u8fce\u63d0\u4ea4Issue\u548cPull Request\uff01\n\n## \u4f5c\u8005\n\nFlikify - reqkeeper@92coco.cn\n\n\u9879\u76ee\u94fe\u63a5: https://github.com/Flikify/reqkeeper\n",
    "bugtrack_url": null,
    "license": "MIT",
    "summary": "\u4e00\u4e2a\u529f\u80fd\u5f3a\u5927\u7684HTTP\u4f1a\u8bdd\u6301\u4e45\u5316\u5de5\u5177",
    "version": "1.0.0",
    "project_urls": {
        "Bug Tracker": "https://github.com/Flikify/reqkeeper/issues",
        "Documentation": "https://github.com/Flikify/reqkeeper#readme",
        "Homepage": "https://github.com/Flikify/reqkeeper",
        "Source Code": "https://github.com/Flikify/reqkeeper"
    },
    "split_keywords": [
        "http",
        " requests",
        " session",
        " persistent",
        " cookies",
        " retry",
        " interceptor"
    ],
    "urls": [
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "99aedd4e117f1bbb7ae63a7f972a20b29448ca1ca2b9d9d45eb20f7e252e6eb8",
                "md5": "87ae5526555c85087fea1b15677b4d70",
                "sha256": "1ef6a3ca6a34c4a9bd8ea0a2efd9f234ef75e9198d0be88cb73044b757f13b4b"
            },
            "downloads": -1,
            "filename": "reqkeeper-1.0.0-py3-none-any.whl",
            "has_sig": false,
            "md5_digest": "87ae5526555c85087fea1b15677b4d70",
            "packagetype": "bdist_wheel",
            "python_version": "py3",
            "requires_python": ">=3.7",
            "size": 9897,
            "upload_time": "2025-08-12T03:13:01",
            "upload_time_iso_8601": "2025-08-12T03:13:01.235683Z",
            "url": "https://files.pythonhosted.org/packages/99/ae/dd4e117f1bbb7ae63a7f972a20b29448ca1ca2b9d9d45eb20f7e252e6eb8/reqkeeper-1.0.0-py3-none-any.whl",
            "yanked": false,
            "yanked_reason": null
        },
        {
            "comment_text": null,
            "digests": {
                "blake2b_256": "d046aac0808424ea440920ce6528c0906cc5342509b30ccc90a8156d283f8c54",
                "md5": "4d091b351fb1f52b7728c4deeefa3bb2",
                "sha256": "6d095b842daab1ce726d58d92cfbe9b16231943bd279945beb72095bb5850d1b"
            },
            "downloads": -1,
            "filename": "reqkeeper-1.0.0.tar.gz",
            "has_sig": false,
            "md5_digest": "4d091b351fb1f52b7728c4deeefa3bb2",
            "packagetype": "sdist",
            "python_version": "source",
            "requires_python": ">=3.7",
            "size": 12312,
            "upload_time": "2025-08-12T03:13:02",
            "upload_time_iso_8601": "2025-08-12T03:13:02.905996Z",
            "url": "https://files.pythonhosted.org/packages/d0/46/aac0808424ea440920ce6528c0906cc5342509b30ccc90a8156d283f8c54/reqkeeper-1.0.0.tar.gz",
            "yanked": false,
            "yanked_reason": null
        }
    ],
    "upload_time": "2025-08-12 03:13:02",
    "github": true,
    "gitlab": false,
    "bitbucket": false,
    "codeberg": false,
    "github_user": "Flikify",
    "github_project": "reqkeeper",
    "travis_ci": false,
    "coveralls": false,
    "github_actions": false,
    "requirements": [
        {
            "name": "requests",
            "specs": [
                [
                    ">=",
                    "2.25.0"
                ]
            ]
        },
        {
            "name": "tenacity",
            "specs": [
                [
                    ">=",
                    "8.0.0"
                ]
            ]
        },
        {
            "name": "urllib3",
            "specs": [
                [
                    ">=",
                    "1.26.0"
                ]
            ]
        }
    ],
    "lcname": "reqkeeper"
}
        
Elapsed time: 1.14390s