# Python 115 网盘客户端.
![PyPI - Python Version](https://img.shields.io/pypi/pyversions/p115client)
![PyPI - Version](https://img.shields.io/pypi/v/p115client)
![PyPI - Downloads](https://img.shields.io/pypi/dm/p115client)
![PyPI - Format](https://img.shields.io/pypi/format/p115client)
![PyPI - Status](https://img.shields.io/pypi/status/p115client)
## 安装
你可以从 [pypi](https://pypi.org/project/p115client/) 安装最新版本
```console
pip install -U p115client
```
## 入门介绍
### 1. 导入模块和创建实例
导入模块
```python
from p115client import P115Client
```
创建客户端对象,需要传入 <kbd>cookies</kbd>,如果不传,则需要扫码登录
```python
cookies = "UID=...; CID=...; SEID=..."
client = P115Client(cookies)
```
如果你的 <kbd>cookies</kbd> 保存在 `~/115-cookies.txt`
```python
from pathlib import Path
client = P115Client(Path("~/115-cookies.txt").expanduser())
```
如果想要在接口返回时自动捕获 405 HTTP 响应码,进行自动扫码,并把更新后的 <kbd>cookies</kbd> 写回文件,然后重试接口调用
```python
client = P115Client(Path("~/115-cookies.txt").expanduser(), check_for_relogin=True)
```
所以综上,推荐的初始化代码为
```python
from p115client import P115Client
from pathlib import Path
client = P115Client(Path("~/115-cookies.txt").expanduser(), check_for_relogin=True)
```
### 2. 接口调用
所有需要直接或间接执行 HTTP 请求的接口,都有同步和异步的调用方式
```python
# 同步调用
client.method(payload)
client.method(payload, async_=False)
# 异步调用
await client.method(payload, async_=True)
```
从根本上讲,除了几个 `staticmethod`,它们都会调用 `P115Client.request`
```python
url = "https://webapi.115.com/files"
response = client.request(url=url, params={"cid": 0, "show_dir": 1})
```
当你需要构建自己的扩展模块,以增加一些新的 115 web 接口时,就需要用到此方法了
```python
from collections.abc import Coroutine
from typing import overload, Any, Literal
from p115client import P115Client
class MyCustom115Client(P115Client):
@overload
def foo(
self,
payload: dict,
/,
async_: Literal[False] = False,
**request_kwargs,
) -> dict:
...
@overload
def foo(
self,
payload: dict,
/,
async_: Literal[True],
**request_kwargs,
) -> Coroutine[Any, Any, dict]:
...
def foo(
self,
payload: dict,
/,
async_: bool = False,
**request_kwargs,
) -> dict | Coroutine[Any, Any, dict]:
api = "https://webapi.115.com/foo"
return self.request(
api,
method="GET",
params=payload,
async_=async_,
**request_kwargs,
)
@overload
def bar(
self,
payload: dict,
/,
async_: Literal[False] = False,
**request_kwargs,
) -> dict:
...
@overload
def bar(
self,
payload: dict,
/,
async_: Literal[True],
**request_kwargs,
) -> Coroutine[Any, Any, dict]:
...
def bar(
self,
payload: dict,
/,
async_: bool = False,
**request_kwargs,
) -> dict | Coroutine[Any, Any, dict]:
api = "https://webapi.115.com/bar"
return self.request(
api,
method="POST",
data=payload,
async_=async_,
**request_kwargs,
)
```
### 3. 检查响应
接口被调用后,如果返回的是 dict 类型的数据(说明原本是 JSON),则可以用 `p115client.check_response` 执行检查。首先会查看其中名为 "state" 的键的对应值,如果为 True、1 或不存在,则原样返回被检查的数据;否则,"state" 的对应值大概是 False 或 0,说明有问题出现,会根据实际情况抛出一个异常,但都是 `p115client.P115OSError` 的实例。
```python
from p115client import check_response
# 检查同步调用
data = check_response(client.method(payload))
# 检查异步调用
data = check_response(await client.method(payload, async_=True))
```
### 4. 辅助工具
一些简单的封装工具可能是必要的,特别是那种实现起来代码量比较少,可以封装成单个函数的。我把平常使用过程中,积累的一些经验具体化为一组工具函数。这些工具函数分别有着不同的功能,如果组合起来使用,或许能解决很多问题。
```python
from p115client import tool
```
## 其它资源
- 如果你需要更详细的文档,特别是关于各种接口的信息,可以阅读
[https://p115client.readthedocs.io/en/latest/](https://p115client.readthedocs.io/en/latest/)
- 如果你想要一组更高级的封装,特别是一组文件系统的操作集合,可以使用
[https://pypi.org/project/python-115/](https://pypi.org/project/python-115/)
Raw data
{
"_id": null,
"home_page": "https://github.com/ChenyangGao/p115client",
"name": "p115client",
"maintainer": null,
"docs_url": null,
"requires_python": "<4.0,>=3.11",
"maintainer_email": null,
"keywords": "115, webdisk, client",
"author": "ChenyangGao",
"author_email": "wosiwujm@gmail.com",
"download_url": "https://files.pythonhosted.org/packages/24/50/f6bf41204aa5bfea08c2ba65673ab60886b23cadf9f4dde5281cd80e3f94/p115client-0.0.3.7.10.tar.gz",
"platform": null,
"description": "# Python 115 \u7f51\u76d8\u5ba2\u6237\u7aef.\n\n![PyPI - Python Version](https://img.shields.io/pypi/pyversions/p115client)\n![PyPI - Version](https://img.shields.io/pypi/v/p115client)\n![PyPI - Downloads](https://img.shields.io/pypi/dm/p115client)\n![PyPI - Format](https://img.shields.io/pypi/format/p115client)\n![PyPI - Status](https://img.shields.io/pypi/status/p115client)\n\n## \u5b89\u88c5\n\n\u4f60\u53ef\u4ee5\u4ece [pypi](https://pypi.org/project/p115client/) \u5b89\u88c5\u6700\u65b0\u7248\u672c\n\n```console\npip install -U p115client\n```\n\n## \u5165\u95e8\u4ecb\u7ecd\n\n### 1. \u5bfc\u5165\u6a21\u5757\u548c\u521b\u5efa\u5b9e\u4f8b\n\n\u5bfc\u5165\u6a21\u5757\n\n```python\nfrom p115client import P115Client\n```\n\n\u521b\u5efa\u5ba2\u6237\u7aef\u5bf9\u8c61\uff0c\u9700\u8981\u4f20\u5165 <kbd>cookies</kbd>\uff0c\u5982\u679c\u4e0d\u4f20\uff0c\u5219\u9700\u8981\u626b\u7801\u767b\u5f55\n\n```python\ncookies = \"UID=...; CID=...; SEID=...\"\nclient = P115Client(cookies)\n```\n\n\u5982\u679c\u4f60\u7684 <kbd>cookies</kbd> \u4fdd\u5b58\u5728 `~/115-cookies.txt`\n\n```python\nfrom pathlib import Path\n\nclient = P115Client(Path(\"~/115-cookies.txt\").expanduser())\n```\n\n\u5982\u679c\u60f3\u8981\u5728\u63a5\u53e3\u8fd4\u56de\u65f6\u81ea\u52a8\u6355\u83b7 405 HTTP \u54cd\u5e94\u7801\uff0c\u8fdb\u884c\u81ea\u52a8\u626b\u7801\uff0c\u5e76\u628a\u66f4\u65b0\u540e\u7684 <kbd>cookies</kbd> \u5199\u56de\u6587\u4ef6\uff0c\u7136\u540e\u91cd\u8bd5\u63a5\u53e3\u8c03\u7528\n\n```python\nclient = P115Client(Path(\"~/115-cookies.txt\").expanduser(), check_for_relogin=True)\n```\n\n\u6240\u4ee5\u7efc\u4e0a\uff0c\u63a8\u8350\u7684\u521d\u59cb\u5316\u4ee3\u7801\u4e3a\n\n```python\nfrom p115client import P115Client\nfrom pathlib import Path\n\nclient = P115Client(Path(\"~/115-cookies.txt\").expanduser(), check_for_relogin=True)\n```\n\n### 2. \u63a5\u53e3\u8c03\u7528\n\n\u6240\u6709\u9700\u8981\u76f4\u63a5\u6216\u95f4\u63a5\u6267\u884c HTTP \u8bf7\u6c42\u7684\u63a5\u53e3\uff0c\u90fd\u6709\u540c\u6b65\u548c\u5f02\u6b65\u7684\u8c03\u7528\u65b9\u5f0f\n\n```python\n# \u540c\u6b65\u8c03\u7528\nclient.method(payload)\nclient.method(payload, async_=False)\n\n# \u5f02\u6b65\u8c03\u7528\nawait client.method(payload, async_=True)\n```\n\n\u4ece\u6839\u672c\u4e0a\u8bb2\uff0c\u9664\u4e86\u51e0\u4e2a `staticmethod`\uff0c\u5b83\u4eec\u90fd\u4f1a\u8c03\u7528 `P115Client.request`\n\n```python\nurl = \"https://webapi.115.com/files\"\nresponse = client.request(url=url, params={\"cid\": 0, \"show_dir\": 1})\n```\n\n\u5f53\u4f60\u9700\u8981\u6784\u5efa\u81ea\u5df1\u7684\u6269\u5c55\u6a21\u5757\uff0c\u4ee5\u589e\u52a0\u4e00\u4e9b\u65b0\u7684 115 web \u63a5\u53e3\u65f6\uff0c\u5c31\u9700\u8981\u7528\u5230\u6b64\u65b9\u6cd5\u4e86\n\n```python\nfrom collections.abc import Coroutine\nfrom typing import overload, Any, Literal\n\nfrom p115client import P115Client\n\nclass MyCustom115Client(P115Client):\n\n @overload\n def foo(\n self, \n payload: dict, \n /, \n async_: Literal[False] = False, \n **request_kwargs, \n ) -> dict:\n ...\n @overload\n def foo(\n self, \n payload: dict, \n /, \n async_: Literal[True], \n **request_kwargs, \n ) -> Coroutine[Any, Any, dict]:\n ...\n def foo(\n self, \n payload: dict, \n /, \n async_: bool = False, \n **request_kwargs, \n ) -> dict | Coroutine[Any, Any, dict]:\n api = \"https://webapi.115.com/foo\"\n return self.request(\n api, \n method=\"GET\", \n params=payload, \n async_=async_, \n **request_kwargs, \n )\n\n @overload\n def bar(\n self, \n payload: dict, \n /, \n async_: Literal[False] = False, \n **request_kwargs, \n ) -> dict:\n ...\n @overload\n def bar(\n self, \n payload: dict, \n /, \n async_: Literal[True], \n **request_kwargs, \n ) -> Coroutine[Any, Any, dict]:\n ...\n def bar(\n self, \n payload: dict, \n /, \n async_: bool = False, \n **request_kwargs, \n ) -> dict | Coroutine[Any, Any, dict]:\n api = \"https://webapi.115.com/bar\"\n return self.request(\n api, \n method=\"POST\", \n data=payload, \n async_=async_, \n **request_kwargs, \n )\n```\n\n### 3. \u68c0\u67e5\u54cd\u5e94\n\n\u63a5\u53e3\u88ab\u8c03\u7528\u540e\uff0c\u5982\u679c\u8fd4\u56de\u7684\u662f dict \u7c7b\u578b\u7684\u6570\u636e\uff08\u8bf4\u660e\u539f\u672c\u662f JSON\uff09\uff0c\u5219\u53ef\u4ee5\u7528 `p115client.check_response` \u6267\u884c\u68c0\u67e5\u3002\u9996\u5148\u4f1a\u67e5\u770b\u5176\u4e2d\u540d\u4e3a \"state\" \u7684\u952e\u7684\u5bf9\u5e94\u503c\uff0c\u5982\u679c\u4e3a True\u30011 \u6216\u4e0d\u5b58\u5728\uff0c\u5219\u539f\u6837\u8fd4\u56de\u88ab\u68c0\u67e5\u7684\u6570\u636e\uff1b\u5426\u5219\uff0c\"state\" \u7684\u5bf9\u5e94\u503c\u5927\u6982\u662f False \u6216 0\uff0c\u8bf4\u660e\u6709\u95ee\u9898\u51fa\u73b0\uff0c\u4f1a\u6839\u636e\u5b9e\u9645\u60c5\u51b5\u629b\u51fa\u4e00\u4e2a\u5f02\u5e38\uff0c\u4f46\u90fd\u662f `p115client.P115OSError` \u7684\u5b9e\u4f8b\u3002\n\n```python\nfrom p115client import check_response\n\n# \u68c0\u67e5\u540c\u6b65\u8c03\u7528\ndata = check_response(client.method(payload))\n# \u68c0\u67e5\u5f02\u6b65\u8c03\u7528\ndata = check_response(await client.method(payload, async_=True))\n```\n\n### 4. \u8f85\u52a9\u5de5\u5177\n\n\u4e00\u4e9b\u7b80\u5355\u7684\u5c01\u88c5\u5de5\u5177\u53ef\u80fd\u662f\u5fc5\u8981\u7684\uff0c\u7279\u522b\u662f\u90a3\u79cd\u5b9e\u73b0\u8d77\u6765\u4ee3\u7801\u91cf\u6bd4\u8f83\u5c11\uff0c\u53ef\u4ee5\u5c01\u88c5\u6210\u5355\u4e2a\u51fd\u6570\u7684\u3002\u6211\u628a\u5e73\u5e38\u4f7f\u7528\u8fc7\u7a0b\u4e2d\uff0c\u79ef\u7d2f\u7684\u4e00\u4e9b\u7ecf\u9a8c\u5177\u4f53\u5316\u4e3a\u4e00\u7ec4\u5de5\u5177\u51fd\u6570\u3002\u8fd9\u4e9b\u5de5\u5177\u51fd\u6570\u5206\u522b\u6709\u7740\u4e0d\u540c\u7684\u529f\u80fd\uff0c\u5982\u679c\u7ec4\u5408\u8d77\u6765\u4f7f\u7528\uff0c\u6216\u8bb8\u80fd\u89e3\u51b3\u5f88\u591a\u95ee\u9898\u3002\n\n```python\nfrom p115client import tool\n```\n\n## \u5176\u5b83\u8d44\u6e90\n\n- \u5982\u679c\u4f60\u9700\u8981\u66f4\u8be6\u7ec6\u7684\u6587\u6863\uff0c\u7279\u522b\u662f\u5173\u4e8e\u5404\u79cd\u63a5\u53e3\u7684\u4fe1\u606f\uff0c\u53ef\u4ee5\u9605\u8bfb\n\n [https://p115client.readthedocs.io/en/latest/](https://p115client.readthedocs.io/en/latest/)\n\n- \u5982\u679c\u4f60\u60f3\u8981\u4e00\u7ec4\u66f4\u9ad8\u7ea7\u7684\u5c01\u88c5\uff0c\u7279\u522b\u662f\u4e00\u7ec4\u6587\u4ef6\u7cfb\u7edf\u7684\u64cd\u4f5c\u96c6\u5408\uff0c\u53ef\u4ee5\u4f7f\u7528\n\n [https://pypi.org/project/python-115/](https://pypi.org/project/python-115/)\n\n",
"bugtrack_url": null,
"license": "MIT",
"summary": "Python 115 webdisk client.",
"version": "0.0.3.7.10",
"project_urls": {
"Documentation": "https://p115client.readthedocs.io",
"Homepage": "https://github.com/ChenyangGao/p115client",
"Repository": "https://github.com/ChenyangGao/p115client"
},
"split_keywords": [
"115",
" webdisk",
" client"
],
"urls": [
{
"comment_text": "",
"digests": {
"blake2b_256": "3153c8e8e29059996c149c8dd19a74a0f5b2d8eeba61d7b9b39c90b71919a103",
"md5": "107a79b92e4ca15166b081323f4b3a3b",
"sha256": "62d41bbf87b0c54602b5e1b2cda34d60e2e16fa8ddc97bff08f1c892f82c724b"
},
"downloads": -1,
"filename": "p115client-0.0.3.7.10-py3-none-any.whl",
"has_sig": false,
"md5_digest": "107a79b92e4ca15166b081323f4b3a3b",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": "<4.0,>=3.11",
"size": 97104,
"upload_time": "2024-11-23T07:55:59",
"upload_time_iso_8601": "2024-11-23T07:55:59.970403Z",
"url": "https://files.pythonhosted.org/packages/31/53/c8e8e29059996c149c8dd19a74a0f5b2d8eeba61d7b9b39c90b71919a103/p115client-0.0.3.7.10-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": "",
"digests": {
"blake2b_256": "2450f6bf41204aa5bfea08c2ba65673ab60886b23cadf9f4dde5281cd80e3f94",
"md5": "c86ee201ddcee438a0d4b4bbb007f195",
"sha256": "e5bedd5fd8cfd403280665227dd4c4d198d1422df611906aadf9092319d3ae8b"
},
"downloads": -1,
"filename": "p115client-0.0.3.7.10.tar.gz",
"has_sig": false,
"md5_digest": "c86ee201ddcee438a0d4b4bbb007f195",
"packagetype": "sdist",
"python_version": "source",
"requires_python": "<4.0,>=3.11",
"size": 88577,
"upload_time": "2024-11-23T07:56:02",
"upload_time_iso_8601": "2024-11-23T07:56:02.170807Z",
"url": "https://files.pythonhosted.org/packages/24/50/f6bf41204aa5bfea08c2ba65673ab60886b23cadf9f4dde5281cd80e3f94/p115client-0.0.3.7.10.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2024-11-23 07:56:02",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ChenyangGao",
"github_project": "p115client",
"travis_ci": false,
"coveralls": false,
"github_actions": false,
"lcname": "p115client"
}