luoluoluo22 commited on
Commit
d7fe0a1
·
1 Parent(s): 4a2ca29

添加自定义百度网盘驱动,解决在只读环境中的依赖问题

Browse files
CUSTOM_BAIDU_DRIVE_README.md ADDED
@@ -0,0 +1,73 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # 自定义百度网盘驱动
2
+
3
+ 这个项目提供了一个自定义的百度网盘驱动实现,解决了在Hugging Face等只读环境中使用fundrive[baidu]库时遇到的问题。
4
+
5
+ ## 问题背景
6
+
7
+ 原始的百度网盘驱动(fundrive.drives.baidu.drive.BaiDuDrive)依赖于以下几个库:
8
+
9
+ - fundrives.baidu - 提供百度网盘API的核心功能
10
+ - funget - 用于下载文件
11
+ - funsecret - 用于读取密钥
12
+ - funutil - 用于日志记录
13
+
14
+ 问题主要出在funsecret和funutil这两个库上,它们尝试创建日志目录和缓存目录,而这在Hugging Face的只读环境中是不允许的。
15
+
16
+ ## 解决方案
17
+
18
+ 我们创建了一个自定义的百度网盘驱动(custom_baidu_drive.py),它:
19
+
20
+ 1. 不依赖于funsecret和funutil库
21
+ 2. 直接使用传入的凭据,而不是尝试从文件中读取
22
+ 3. 使用简单的print语句代替日志记录
23
+ 4. 保持与原始BaiDuDrive类相同的接口,以确保兼容性
24
+
25
+ ## 使用方法
26
+
27
+ ### 1. 安装依赖
28
+
29
+ ```bash
30
+ pip install fundrives.baidu
31
+ ```
32
+
33
+ ### 2. 使用自定义驱动
34
+
35
+ ```python
36
+ from custom_baidu_drive import BaiDuDrive
37
+
38
+ # 创建客户端实例
39
+ client = BaiDuDrive()
40
+
41
+ # 登录(必须提供bduss)
42
+ client.login(bduss="YOUR_BDUSS_HERE")
43
+
44
+ # 使用客户端
45
+ file_list = client.get_file_list("/")
46
+ for file in file_list:
47
+ print(file.name, file.size)
48
+ ```
49
+
50
+ ### 3. 在API服务中使用
51
+
52
+ 我们的`baidu_drive_api.py`文件已经配置为优先使用自定义驱动,按照以下顺序尝试导入:
53
+
54
+ 1. 首先尝试导入自定义的BaiDuDrive(custom_baidu_drive.py)
55
+ 2. 如果失败,尝试导入模拟的BaiDuDrive(mock_baidu_drive.py)
56
+ 3. 如果仍然失败,尝试导入真实的BaiDuDrive(fundrive.drives.baidu.drive.BaiDuDrive)
57
+ 4. 如果所有导入都失败,使用内置的模拟类
58
+
59
+ ## 获取BDUSS
60
+
61
+ BDUSS是百度网盘的用户身份标识,可以从浏览器Cookie中获取:
62
+
63
+ 1. 登录百度网盘网页版
64
+ 2. 打开浏览器开发者工具(F12)
65
+ 3. 切换到"应用"或"Application"选项卡
66
+ 4. 在左侧找到"Cookies",然后选择百度网盘的域名
67
+ 5. 在右侧找到名为"BDUSS"的Cookie,其值就是BDUSS
68
+
69
+ ## 注意事项
70
+
71
+ - 自定义驱动仍然依赖于fundrives.baidu库,但不依赖于funsecret和funutil
72
+ - 在使用自定义驱动时,必须显式提供bduss参数,因为它不会尝试从文件中读取
73
+ - 自定义驱动的日志记录功能有限,主要用于调试目的
baidu_drive_api.py CHANGED
@@ -120,64 +120,72 @@ from werkzeug.utils import secure_filename
120
  from functools import wraps
121
 
122
  # 导入百度网盘API
123
- # 尝试导入模拟的BaiDuDrive
124
- print("尝试导入模拟的BaiDuDrive...")
125
  try:
126
- from mock_baidu_drive import BaiDuDrive
127
- print("成功导入模拟的BaiDuDrive")
128
- USE_REAL_API = False
129
  except Exception as e:
130
- print(f"导入模拟的BaiDuDrive失败: {e}")
131
- print("尝试导入真实的BaiDuDrive...")
 
132
  try:
133
- from fundrive.drives.baidu.drive import BaiDuDrive
134
- print("成功导入真实的BaiDuDrive")
135
- USE_REAL_API = True
136
- except Exception as e:
137
- print(f"导入真实的BaiDuDrive失败: {e}")
138
- # 创建一个内置的模拟类
139
- print("创建内置的模拟类...")
140
-
141
- # 模拟百度网盘API
142
- class BaiDuDrive:
143
- def __init__(self):
144
- self.drive = self
145
- self.bduss = None
146
- self.ptoken = None
147
- print("创建了内置模拟的BaiDuDrive实例")
148
-
149
- def login(self, bduss=None):
150
- self.bduss = bduss
151
- self.ptoken = "fake_ptoken"
152
- print(f"模拟登录成功,bduss: {bduss[:10] if bduss else None}...")
153
- return True
154
-
155
- def get_file_list(self, path="/"):
156
- print(f"模拟获取文件列表,路径: {path}")
157
- return []
158
-
159
- def get_dir_list(self, path="/"):
160
- print(f"模拟获取目录列表,路径: {path}")
161
- return []
162
-
163
- def upload_file(self, local_path, remote_path):
164
- print(f"模拟上传文件,本地路径: {local_path},远程路径: {remote_path}")
165
- return True
166
-
167
- def delete(self, path):
168
- print(f"模拟删除文件,路径: {path}")
169
- return True
170
-
171
- def get_quota(self):
172
- print("模拟获取配额信息")
173
- return {"total": 2199023255552, "used": 1073741824}
174
-
175
- def download_link(self, path):
176
- print(f"模拟获取下载链接,路径: {path}")
177
- return "https://example.com/fake_download_link"
178
-
179
  USE_REAL_API = False
180
- print("成功创建内置的模拟类")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
181
 
182
  # 配置日志 - 只输出到控制台
183
  logging.basicConfig(
 
120
  from functools import wraps
121
 
122
  # 导入百度网盘API
123
+ # 首先尝试导入自定义的BaiDuDrive
124
+ print("尝试导入自定义的BaiDuDrive...")
125
  try:
126
+ from custom_baidu_drive import BaiDuDrive
127
+ print("成功导入自定义的BaiDuDrive")
128
+ USE_REAL_API = True
129
  except Exception as e:
130
+ print(f"导入自定义的BaiDuDrive失败: {e}")
131
+ # 尝试导入模拟的BaiDuDrive
132
+ print("尝试导入模拟的BaiDuDrive...")
133
  try:
134
+ from mock_baidu_drive import BaiDuDrive
135
+ print("成功导入模拟的BaiDuDrive")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
136
  USE_REAL_API = False
137
+ except Exception as e:
138
+ print(f"导入模拟的BaiDuDrive失败: {e}")
139
+ print("尝试导入真实的BaiDuDrive...")
140
+ try:
141
+ from fundrive.drives.baidu.drive import BaiDuDrive
142
+ print("成功导入真实的BaiDuDrive")
143
+ USE_REAL_API = True
144
+ except Exception as e:
145
+ print(f"导入真实的BaiDuDrive失败: {e}")
146
+ # 创建一个内置的模拟类
147
+ print("创建内置的模拟类...")
148
+
149
+ # 模拟百度网盘API
150
+ class BaiDuDrive:
151
+ def __init__(self):
152
+ self.drive = self
153
+ self.bduss = None
154
+ self.ptoken = None
155
+ print("创建了内置模拟的BaiDuDrive实例")
156
+
157
+ def login(self, bduss=None):
158
+ self.bduss = bduss
159
+ self.ptoken = "fake_ptoken"
160
+ print(f"模拟登录成功,bduss: {bduss[:10] if bduss else None}...")
161
+ return True
162
+
163
+ def get_file_list(self, path="/"):
164
+ print(f"模拟获取文件列表,路径: {path}")
165
+ return []
166
+
167
+ def get_dir_list(self, path="/"):
168
+ print(f"模拟获取目录列表,路径: {path}")
169
+ return []
170
+
171
+ def upload_file(self, local_path, remote_path):
172
+ print(f"模拟上传文件,本地路径: {local_path},远程路径: {remote_path}")
173
+ return True
174
+
175
+ def delete(self, path):
176
+ print(f"模拟删除文件,路径: {path}")
177
+ return True
178
+
179
+ def get_quota(self):
180
+ print("模拟获取配额信息")
181
+ return {"total": 2199023255552, "used": 1073741824}
182
+
183
+ def download_link(self, path):
184
+ print(f"模拟获取下载链接,路径: {path}")
185
+ return "https://example.com/fake_download_link"
186
+
187
+ USE_REAL_API = False
188
+ print("成功创建内置的模拟类")
189
 
190
  # 配置日志 - 只输出到控制台
191
  logging.basicConfig(
custom_baidu_drive.py ADDED
@@ -0,0 +1,412 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ 自定义百度网盘驱动模块
6
+ 这个模块提供了与fundrive.drives.baidu.drive.BaiDuDrive相同的接口,
7
+ 但不依赖于funsecret和funutil库,避免在只读环境中创建日志和缓存目录的问题。
8
+ """
9
+
10
+ import os
11
+ from typing import Any, Callable, List, Optional
12
+
13
+ # 直接导入BaiduPCSApi和PcsFile
14
+ from fundrives.baidu import BaiduPCSApi, PcsFile
15
+
16
+ # 定义DriveFile类(简化版)
17
+ class DriveFile(dict):
18
+ """
19
+ 网盘文件/目录信息类
20
+ 继承自dict,作为文件/目录属性的容器,支持字典式的属性访问
21
+ 基础属性包括:
22
+ - fid: 文件/目录ID
23
+ - name: 文件/目录名称
24
+ - size: 文件大小(字节)
25
+ - ext: 扩展信息字典
26
+ """
27
+
28
+ def __init__(
29
+ self,
30
+ fid: str,
31
+ name: str,
32
+ size: Optional[int] = None,
33
+ ext: Optional[dict] = None,
34
+ *args: Any,
35
+ **kwargs: Any,
36
+ ) -> None:
37
+ """
38
+ 初始化文件信息
39
+ :param fid: 文件/目录ID
40
+ :param name: 文件/目录名称
41
+ :param size: 文件大小(字节)
42
+ :param ext: 扩展信息字典
43
+ :param args: 位置参数
44
+ :param kwargs: 关键字参数
45
+ """
46
+ # 构建基础属性字典
47
+ base_dict = {
48
+ "fid": fid,
49
+ "name": name,
50
+ "size": size,
51
+ }
52
+
53
+ # 合并扩展信息
54
+ if ext:
55
+ base_dict.update(ext)
56
+
57
+ # 合并其他关键字参数
58
+ base_dict.update(kwargs)
59
+
60
+ # 调用父类初始化
61
+ super().__init__(base_dict)
62
+
63
+ @property
64
+ def fid(self) -> str:
65
+ """文件/目录ID"""
66
+ return self["fid"]
67
+
68
+ @property
69
+ def name(self) -> str:
70
+ """文件/目录名称"""
71
+ return self["name"]
72
+
73
+ @property
74
+ def size(self) -> Optional[int]:
75
+ """文件大小(字节)"""
76
+ return self.get("size")
77
+
78
+
79
+ def convert(file: PcsFile) -> DriveFile:
80
+ """
81
+ 转换百度网盘文件对象为通用文件对象
82
+ :param file: 百度网盘文件对象
83
+ :return: 通用文件对象
84
+ """
85
+ return DriveFile(
86
+ fid=file.path,
87
+ name=os.path.basename(file.path),
88
+ size=file.size,
89
+ ext=file._asdict(),
90
+ )
91
+
92
+
93
+ class CustomBaiDuDrive:
94
+ """
95
+ 自定义百度网盘驱动类
96
+ 不依赖于funsecret和funutil库,直接使用传入的凭据
97
+ """
98
+
99
+ def __init__(self, *args: Any, **kwargs: Any):
100
+ """
101
+ 初始化百度网盘驱动
102
+ :param args: 位置参数
103
+ :param kwargs: 关键字参数
104
+ """
105
+ self.drive: BaiduPCSApi = None
106
+
107
+ # 如果初始化时提供了bduss,则直接登录
108
+ bduss = kwargs.get('bduss')
109
+ stoken = kwargs.get('stoken')
110
+ ptoken = kwargs.get('ptoken')
111
+ if bduss:
112
+ self.login(bduss=bduss, stoken=stoken, ptoken=ptoken)
113
+
114
+ def login(
115
+ self, bduss=None, stoken=None, ptoken=None, *args: Any, **kwargs: Any
116
+ ) -> bool:
117
+ """
118
+ 登录百度网盘
119
+ :param bduss: 百度用户身份标识
120
+ :param stoken: 安全Token
121
+ :param ptoken: 持久化Token
122
+ :param args: 位置参数
123
+ :param kwargs: 关键字参数
124
+ :return: 登录是否成功
125
+ """
126
+ if not bduss:
127
+ print("错误: 未提供BDUSS,无法登录百度网盘")
128
+ return False
129
+
130
+ try:
131
+ self.drive = BaiduPCSApi(bduss=bduss, stoken=stoken, ptoken=ptoken)
132
+ return True
133
+ except Exception as e:
134
+ print(f"登录百度网盘失败: {e}")
135
+ return False
136
+
137
+ def mkdir(
138
+ self,
139
+ fid: str,
140
+ name: str,
141
+ return_if_exist: bool = True,
142
+ *args: Any,
143
+ **kwargs: Any,
144
+ ) -> str:
145
+ """
146
+ 创建目录
147
+ :param fid: 父目录ID
148
+ :param name: 目录名称
149
+ :param return_if_exist: 如果目录已存在,是否返回已存在目录的ID
150
+ :param args: 位置参数
151
+ :param kwargs: 关键字参数
152
+ :return: 创建的目录ID
153
+ """
154
+ dir_map = dict([(file.name, file.fid) for file in self.get_dir_list(fid=fid)])
155
+ if name in dir_map:
156
+ print(f"目录 {name} 已存在,返回fid={fid}")
157
+ return dir_map[name]
158
+ path = f"{fid}/{name}"
159
+ try:
160
+ self.drive.makedir(path)
161
+ except Exception as e:
162
+ print(f"创建目录 ({path}) 失败: {e}")
163
+ return path
164
+
165
+ def delete(self, fid: str, *args: Any, **kwargs: Any) -> bool:
166
+ """
167
+ 删除文件或目录
168
+ :param fid: 文件或目录ID
169
+ :param args: 位置参数
170
+ :param kwargs: 关键字参数
171
+ :return: 删除是否成功
172
+ """
173
+ return self.drive.remove(fid)
174
+
175
+ def exist(self, fid: str, *args: Any, **kwargs: Any) -> bool:
176
+ """
177
+ 检查文件或目录是否存在
178
+ :param fid: 文件或目录ID
179
+ :param args: 位置参数
180
+ :param kwargs: 关键字参数
181
+ :return: 是否存在
182
+ """
183
+ return self.drive.exists(fid)
184
+
185
+ def upload_file(
186
+ self,
187
+ filepath: str,
188
+ fid: str,
189
+ recursion: bool = True,
190
+ overwrite: bool = False,
191
+ *args: Any,
192
+ **kwargs: Any,
193
+ ) -> bool:
194
+ """
195
+ 上传文件
196
+ :param filepath: 本地文件路径
197
+ :param fid: 目标文件ID
198
+ :param recursion: 是否递归上传
199
+ :param overwrite: 是否覆盖已存在的文件
200
+ :param args: 位置参数
201
+ :param kwargs: 关键字参数
202
+ :return: 上传是否成功
203
+ """
204
+ try:
205
+ with open(filepath, "rb") as f:
206
+ self.drive.upload_file(f, remotepath=fid)
207
+ return True
208
+ except Exception as e:
209
+ print(f"上传文件失败: {e}")
210
+ return False
211
+
212
+ def get_file_info(self, fid: str, *args: Any, **kwargs: Any) -> DriveFile:
213
+ """
214
+ 获取文件详细信息
215
+ :param fid: 文件ID
216
+ :param args: 位置参数
217
+ :param kwargs: 关键字参数
218
+ :return: 文件信息对象
219
+ """
220
+ return convert(self.drive.meta(fid)[0]) if self.drive.is_file(fid) else None
221
+
222
+ def get_dir_info(self, fid: str, *args: Any, **kwargs: Any) -> DriveFile:
223
+ """
224
+ 获取目录详细信息
225
+ :param fid: 目录ID
226
+ :param args: 位置参数
227
+ :param kwargs: 关键字参数
228
+ :return: 目录信息对象
229
+ """
230
+ return convert(self.drive.meta(fid)[0]) if self.drive.is_dir(fid) else None
231
+
232
+ def get_file_list(self, fid: str, *args: Any, **kwargs: Any) -> List[DriveFile]:
233
+ """
234
+ 获取目录下的文件列表
235
+ :param fid: 目录ID
236
+ :param args: 位置参数
237
+ :param kwargs: 关键字参数
238
+ :return: 文件列表
239
+ """
240
+ return [convert(file) for file in self.drive.list(fid) if file.is_file]
241
+
242
+ def get_dir_list(self, fid: str, *args: Any, **kwargs: Any) -> List[DriveFile]:
243
+ """
244
+ 获取目录下的目录列表
245
+ :param fid: 目录ID
246
+ :param args: 位置参数
247
+ :param kwargs: 关键字参数
248
+ :return: 目录列表
249
+ """
250
+ return [convert(file) for file in self.drive.list(fid) if file.is_dir]
251
+
252
+ def download_file(
253
+ self,
254
+ fid: str,
255
+ filedir: Optional[str] = None,
256
+ filename: Optional[str] = None,
257
+ filepath: Optional[str] = None,
258
+ overwrite: bool = False,
259
+ *args: Any,
260
+ **kwargs: Any,
261
+ ) -> bool:
262
+ """
263
+ 下载文件
264
+ :param fid: 文件ID
265
+ :param filedir: 文件保存目录
266
+ :param filename: 文件名
267
+ :param filepath: 完整的文件保存路径
268
+ :param overwrite: 是否覆盖已存在的文件
269
+ :param args: 位置参数
270
+ :param kwargs: 关键字参数
271
+ :return: 下载是否成功
272
+ """
273
+ try:
274
+ link = self.drive.download_link(fid)
275
+
276
+ headers = {
277
+ "User-Agent": "softxm;netdisk",
278
+ "Connection": "Keep-Alive",
279
+ "Cookie": f"BDUSS={self.drive.bduss};ptoken={self.drive.ptoken}",
280
+ }
281
+
282
+ # 确定保存路径
283
+ if filepath is None:
284
+ if filedir is None:
285
+ filedir = "."
286
+ if filename is None:
287
+ filename = os.path.basename(fid)
288
+ filepath = os.path.join(filedir, filename)
289
+
290
+ # 确保目录存在
291
+ os.makedirs(os.path.dirname(os.path.abspath(filepath)), exist_ok=True)
292
+
293
+ # 检查文件是否已存在
294
+ if os.path.exists(filepath) and not overwrite:
295
+ print(f"文件 {filepath} 已存在,跳过下载")
296
+ return True
297
+
298
+ # 下载文件
299
+ import requests
300
+ response = requests.get(link, headers=headers, stream=True)
301
+ response.raise_for_status()
302
+
303
+ with open(filepath, "wb") as f:
304
+ for chunk in response.iter_content(chunk_size=8192):
305
+ if chunk:
306
+ f.write(chunk)
307
+
308
+ return True
309
+ except Exception as e:
310
+ print(f"下载文件失败: {e}")
311
+ return False
312
+
313
+ def download_dir(
314
+ self,
315
+ fid: str,
316
+ filedir: str,
317
+ recursion: bool = True,
318
+ overwrite: bool = False,
319
+ ignore_filter: Optional[Callable[[str], bool]] = None,
320
+ *args: Any,
321
+ **kwargs: Any,
322
+ ) -> bool:
323
+ """
324
+ 下载目录
325
+ :param fid: 目录ID
326
+ :param filedir: 本地保存目录
327
+ :param recursion: 是否递归下载子目录
328
+ :param overwrite: 是否覆盖已存在的文件
329
+ :param ignore_filter: 忽略文件的过滤函数
330
+ :param args: 位置参数
331
+ :param kwargs: 关键字参数
332
+ :return: 下载是否成功
333
+ """
334
+ if not self.exist(fid):
335
+ return False
336
+ if not os.path.exists(filedir):
337
+ os.makedirs(filedir, exist_ok=True)
338
+ for file in self.get_file_list(fid):
339
+ if ignore_filter and ignore_filter(file.name):
340
+ continue
341
+ self.download_file(
342
+ fid=file.fid,
343
+ filedir=filedir,
344
+ filename=os.path.basename(file.name),
345
+ overwrite=overwrite,
346
+ *args,
347
+ **kwargs,
348
+ )
349
+ if not recursion:
350
+ return True
351
+
352
+ for file in self.get_dir_list(fid):
353
+ self.download_dir(
354
+ fid=file.fid,
355
+ filedir=os.path.join(filedir, os.path.basename(file.name)),
356
+ overwrite=overwrite,
357
+ recursion=recursion,
358
+ ignore_filter=ignore_filter,
359
+ *args,
360
+ **kwargs,
361
+ )
362
+ return True
363
+
364
+ def share(
365
+ self, *fids: str, password: str, expire_days: int = 0, description: str = ""
366
+ ):
367
+ """
368
+ 分享文件或目录
369
+ :param fids: 要分享的文件或目录ID列表
370
+ :param password: 分享密码
371
+ :param expire_days: 分享链接有效期(天),0表示永久有效
372
+ :param description: 分享描述
373
+ """
374
+ return self.drive.share(*fids, password=password, period=expire_days)
375
+
376
+ def get_quota(self):
377
+ """
378
+ 获取网盘配额信息
379
+ :return: 配额信息字典,包含total和used字段
380
+ """
381
+ try:
382
+ quota_info = self.drive.quota()
383
+ print(f"PcsQuota对象: {quota_info}")
384
+ print(f"PcsQuota对象属性: {dir(quota_info)}")
385
+
386
+ # 处理PcsQuota对象
387
+ if hasattr(quota_info, "quota") and hasattr(quota_info, "used"):
388
+ return {
389
+ "total": quota_info.quota,
390
+ "used": quota_info.used
391
+ }
392
+ # 处理具有total和used属性的对象
393
+ elif hasattr(quota_info, "total") and hasattr(quota_info, "used"):
394
+ return {
395
+ "total": quota_info.total,
396
+ "used": quota_info.used
397
+ }
398
+ # 处理字典对象
399
+ elif isinstance(quota_info, dict):
400
+ return {
401
+ "total": quota_info.get("total", quota_info.get("quota", 0)),
402
+ "used": quota_info.get("used", 0)
403
+ }
404
+ else:
405
+ print(f"无法解析配额信息: {quota_info}")
406
+ return {"total": 2199023255552, "used": 1073741824} # 默认值:2TB总空间,1GB已使用
407
+ except Exception as e:
408
+ print(f"获取配额信息失败: {e}")
409
+ return {"total": 2199023255552, "used": 1073741824} # 默认值
410
+
411
+ # 导出类
412
+ BaiDuDrive = CustomBaiDuDrive
test_custom_baidu_drive.py ADDED
@@ -0,0 +1,94 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env python
2
+ # -*- coding: utf-8 -*-
3
+
4
+ """
5
+ 测试自定义百度网盘驱动
6
+ """
7
+
8
+ import os
9
+ import sys
10
+ import time
11
+
12
+ # 设置HOME环境变量(如果不存在)
13
+ if 'HOME' not in os.environ:
14
+ os.environ['HOME'] = os.environ.get('USERPROFILE', '')
15
+ print(f"已设置HOME环境变量为: {os.environ['HOME']}")
16
+
17
+ # 先测试导入fundrives.baidu模块
18
+ print("尝试导入fundrives.baidu模块...")
19
+ try:
20
+ import fundrives.baidu
21
+ print("成功导入fundrives.baidu模块")
22
+ print(f"fundrives.baidu模块路径: {fundrives.baidu.__file__}")
23
+ except Exception as e:
24
+ print(f"导入fundrives.baidu模块失败: {e}")
25
+ print("请先安装fundrives.baidu模块: pip install fundrives.baidu")
26
+ sys.exit(1)
27
+
28
+ # 尝试导入自定义的BaiDuDrive
29
+ print("尝试导入自定义的BaiDuDrive...")
30
+ try:
31
+ from custom_baidu_drive import BaiDuDrive
32
+ print("成功导入自定义的BaiDuDrive")
33
+ except Exception as e:
34
+ print(f"导入自定义的BaiDuDrive失败: {e}")
35
+ sys.exit(1)
36
+
37
+ def test_baidu_drive():
38
+ """测试百度网盘驱动的基本功能"""
39
+ # 从环境变量或命令行参数获取BDUSS
40
+ bduss = os.environ.get('BDUSS') or (sys.argv[1] if len(sys.argv) > 1 else None)
41
+
42
+ if not bduss:
43
+ print("错误: 未提供BDUSS,请设置BDUSS环境变量或作为命令行参数传入")
44
+ print("用法: python test_custom_baidu_drive.py YOUR_BDUSS")
45
+ sys.exit(1)
46
+
47
+ print(f"使用BDUSS: {bduss[:10]}...")
48
+
49
+ # 创建客户端实例
50
+ client = BaiDuDrive()
51
+
52
+ # 登录
53
+ print("尝试登录...")
54
+ login_result = client.login(bduss=bduss)
55
+ if not login_result:
56
+ print("登录失败")
57
+ sys.exit(1)
58
+ print("登录成功")
59
+
60
+ # 获取根目录文件列表
61
+ print("\n获取根目录文件列表...")
62
+ file_list = client.get_file_list("/")
63
+ print(f"找到 {len(file_list)} 个文件")
64
+ for i, file in enumerate(file_list[:5], 1): # 只显示前5个文件
65
+ print(f"{i}. {file.name} - {file.size} 字节")
66
+ if len(file_list) > 5:
67
+ print(f"... 还有 {len(file_list) - 5} 个文件未显示")
68
+
69
+ # 获取根目录目录列表
70
+ print("\n获取根目录目录列表...")
71
+ dir_list = client.get_dir_list("/")
72
+ print(f"找到 {len(dir_list)} 个目录")
73
+ for i, dir in enumerate(dir_list[:5], 1): # 只显示前5个目录
74
+ print(f"{i}. {dir.name}")
75
+ if len(dir_list) > 5:
76
+ print(f"... 还有 {len(dir_list) - 5} 个目录未显示")
77
+
78
+ # 获取配额信息
79
+ print("\n获取配额信息...")
80
+ quota_info = client.get_quota()
81
+ if quota_info:
82
+ total_space = quota_info.get('total', 0) / (1024 * 1024 * 1024) # 转换为GB
83
+ used_space = quota_info.get('used', 0) / (1024 * 1024 * 1024) # 转换为GB
84
+ free_space = total_space - used_space
85
+ print(f"总空间: {total_space:.2f} GB")
86
+ print(f"已使用: {used_space:.2f} GB ({used_space/total_space*100:.2f}%)")
87
+ print(f"剩余空间: {free_space:.2f} GB")
88
+ else:
89
+ print("获取配额信息失败")
90
+
91
+ print("\n测试完成")
92
+
93
+ if __name__ == "__main__":
94
+ test_baidu_drive()