Skip to content

Commit 1f662fc

Browse files
author
zaxtyson
committed
fixed vip custom folder download error
1 parent 12f28d3 commit 1f662fc

File tree

4 files changed

+62
-17
lines changed

4 files changed

+62
-17
lines changed

README.md

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,13 @@
3232
- API 文档请查看 [wiki](https://github.com/zaxtyson/LanZouCloud-API/wiki) 页面
3333

3434
# 更新日志
35+
36+
## `v2.5.7`
37+
- 修复 VIP 用户分享的递归文件夹无法下载的问题[#49](https://github.com/zaxtyson/LanZouCloud-CMD/issues/49)
38+
- 修复用户描述中带字符串`请输入密码`而文件没有设置提取码导致误判的问题
39+
- `get_folder_info_by_url()` 返回值中添加了子文件夹信息
40+
- `down_dir_by_id()``down_dir_by_url()` 函数增加参数 `recursive` 用于递归下载子文件夹
41+
3542
## `v2.5.6`
3643
- 修复文件删除后解析无效分享链接崩溃的问题 [#36](https://github.com/zaxtyson/LanZouCloud-API/issues/36#issue-674817998)
3744
- 下载同名文件时重命名优化 [#37](https://github.com/zaxtyson/LanZouCloud-API/issues/37)

lanzou/api/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
from lanzou.api.core import LanZouCloud
22

3-
version = '2.5.6'
3+
version = '2.5.7'
44

55
__all__ = ['utils', 'types', 'models', 'LanZouCloud', 'version']

lanzou/api/core.py

Lines changed: 53 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -432,7 +432,7 @@ def get_file_info_by_url(self, share_url, pwd='') -> FileDetail:
432432
return FileDetail(LanZouCloud.FILE_CANCELLED, pwd=pwd, url=share_url)
433433

434434
# 这里获取下载直链 304 重定向前的链接
435-
if '输入密码' in first_page: # 文件设置了提取码时
435+
if 'id="pwdload"' in first_page or 'id="passwddiv"' in first_page: # 文件设置了提取码时
436436
if len(pwd) == 0:
437437
return FileDetail(LanZouCloud.LACK_PASSWORD, pwd=pwd, url=share_url) # 没给提取码直接退出
438438
# data : 'action=downprocess&sign=AGZRbwEwU2IEDQU6BDRUaFc8DzxfMlRjCjTPlVkWzFSYFY7ATpWYw_c_c&p='+pwd,
@@ -1012,9 +1012,10 @@ def get_folder_info_by_url(self, share_url, dir_pwd='') -> FolderDetail:
10121012
html = requests.get(share_url, headers=self._headers).text
10131013
except requests.RequestException:
10141014
return FolderDetail(LanZouCloud.NETWORK_ERROR)
1015-
if '文件不存在' in html:
1015+
if '文件不存在' in html or '文件取消' in html:
10161016
return FolderDetail(LanZouCloud.FILE_CANCELLED)
1017-
if '请输入密码' in html and len(dir_pwd) == 0:
1017+
# 要求输入密码, 用户描述中可能带有"输入密码",所以不用这个字符串判断
1018+
if ('id="pwdload"' in html or 'id="passwddiv"' in html) and len(dir_pwd) == 0:
10181019
return FolderDetail(LanZouCloud.LACK_PASSWORD)
10191020
try:
10201021
# 获取文件需要的参数
@@ -1024,17 +1025,36 @@ def get_folder_info_by_url(self, share_url, dir_pwd='') -> FolderDetail:
10241025
k = re.findall(r"var [0-9a-z]{6} = '([0-9a-z]{15,})';", html)[0]
10251026
# 文件夹的信息
10261027
folder_id = re.findall(r"'fid':'?(\d+)'?,", html)[0]
1027-
folder_name = re.findall(r"var.+?='(.+?)';\n.+document.title", html)[0]
1028-
folder_time = re.findall(r'class="rets">([\d\-]+?)<a', html)[0] # 日期不全 %m-%d
1029-
folder_desc = re.findall(r'id="filename">(.+?)</span>', html) # 无描述时无法完成匹配
1030-
folder_desc = folder_desc[0] if len(folder_desc) == 1 else ''
1028+
folder_name = re.findall(r"var.+?='(.+?)';\n.+document.title", html) or \
1029+
re.findall(r'<div class="user-title">(.+?)</div>', html)
1030+
folder_name = folder_name[0]
1031+
1032+
folder_time = re.findall(r'class="rets">([\d\-]+?)<a', html) # ['%m-%d'] 或者 None (vip自定义)
1033+
folder_time = folder_time[0] if folder_time else datetime.today().strftime("%m-%d") # 没有就设为现在
1034+
folder_desc = re.findall(r'id="filename">(.+?)</span>', html) or \
1035+
re.findall(r'<div class="user-radio-\d"></div>(.+?)</div>', html)
1036+
folder_desc = folder_desc[0] if folder_desc else ""
10311037
except IndexError:
10321038
return FolderDetail(LanZouCloud.FAILED)
10331039

1040+
# 提取子文件夹信息(vip用户分享的文件夹可以递归包含子文件夹)
1041+
sub_folders = FolderList()
1042+
# 文件夹描述放在 filesize 一栏, 迷惑行为
1043+
all_sub_folders = re.findall(
1044+
r'mbxfolder"><a href="(.+?)".+class="filename">(.+?)<div class="filesize">(.+?)</div>', html)
1045+
for url, name, desc in all_sub_folders:
1046+
url = self._host_url + url
1047+
time_str = datetime.today().strftime('%Y-%m-%d') # 网页没有时间信息, 设置为今天
1048+
sub_folders.append(FolderInfo(name=name, desc=desc, url=url, time=time_str, pwd=dir_pwd))
1049+
1050+
# 提取改文件夹下全部文件
10341051
page = 1
10351052
files = FileList()
10361053
while True:
1054+
if page >= 2: # 连续的请求需要稍等一下
1055+
sleep(0.6)
10371056
try:
1057+
logger.debug(f"Parse page {page}...")
10381058
post_data = {'lx': lx, 'pg': page, 'k': k, 't': t, 'fid': folder_id, 'pwd': dir_pwd}
10391059
resp = self._post(self._host_url + '/filemoreajax.php', data=post_data, headers=self._headers).json()
10401060
except (requests.RequestException, AttributeError):
@@ -1058,14 +1078,15 @@ def get_folder_info_by_url(self, share_url, dir_pwd='') -> FolderDetail:
10581078
continue
10591079
else:
10601080
return FolderDetail(LanZouCloud.FAILED) # 其它未知错误
1081+
10611082
# 通过文件的时间信息补全文件夹的年份(如果有文件的话)
10621083
if files: # 最后一个文件上传时间最早,文件夹的创建年份与其相同
10631084
folder_time = files[-1].time.split('-')[0] + '-' + folder_time
10641085
else: # 可恶,没有文件,日期就设置为今年吧
10651086
folder_time = datetime.today().strftime('%Y-%m-%d')
1066-
return FolderDetail(LanZouCloud.SUCCESS,
1067-
FolderInfo(folder_name, folder_id, dir_pwd, folder_time, folder_desc, share_url),
1068-
files)
1087+
1088+
this_folder = FolderInfo(folder_name, folder_id, dir_pwd, folder_time, folder_desc, share_url)
1089+
return FolderDetail(LanZouCloud.SUCCESS, this_folder, files, sub_folders)
10691090

10701091
def get_folder_info_by_id(self, folder_id):
10711092
"""通过 id 获取文件夹及内部文件信息"""
@@ -1173,20 +1194,21 @@ def _down_big_file(self, name, total_size, file_list, save_path, *, callback=Non
11731194
return LanZouCloud.SUCCESS
11741195

11751196
def down_dir_by_url(self, share_url, dir_pwd='', save_path='./Download', *, callback=None, mkdir=True,
1176-
overwrite=False,
1197+
overwrite=False, recursive=False,
11771198
failed_callback=None, downloaded_handler=None) -> int:
11781199
"""通过分享链接下载文件夹
11791200
:param overwrite: 下载时是否覆盖原文件, 对大文件也生效
11801201
:param save_path 文件夹保存路径
11811202
:param mkdir 是否在 save_path 下创建与远程文件夹同名的文件夹
1182-
:param callback: 用于显示单个文件下载进度的回调函数
1203+
:param callback 用于显示单个文件下载进度的回调函数
1204+
:param recursive 是否递归下载子文件夹(vip用户)
11831205
:param failed_callback 用于处理下载失败文件的回调函数,
11841206
def failed_callback(code, file):
11851207
print(f"文件名: {file.name}, 时间: {file.time}, 大小: {file.size}, 类型: {file.type}") # 共有属性
11861208
if hasattr(file, 'url'): # 使用 URL 下载时
1187-
print(f"文件下载失败, 链接: {file.url}, 错误码: code")
1209+
print(f"文件下载失败, 链接: {file.url}, 错误码: {code}")
11881210
else: # 登录后使用 ID 下载时
1189-
print(f"文件下载失败, ID: {file.id}, 错误码: code")
1211+
print(f"文件下载失败, ID: {file.id}, 错误码: {code}")
11901212
:param downloaded_handler: 单个文件下载完成后进一步处理的回调函数 downloaded_handle(file_path)
11911213
"""
11921214
folder_detail = self.get_folder_info_by_url(share_url, dir_pwd)
@@ -1213,10 +1235,18 @@ def failed_callback(code, file):
12131235
if failed_callback is not None:
12141236
failed_callback(code, file)
12151237

1238+
# 如果有子文件夹则递归下载子文件夹
1239+
if recursive and folder_detail.sub_folders:
1240+
for sub_folder in folder_detail.sub_folders:
1241+
self.down_dir_by_url(sub_folder.url, dir_pwd, save_path, callback=callback,
1242+
overwrite=overwrite,
1243+
recursive=True, failed_callback=failed_callback,
1244+
downloaded_handler=downloaded_handler)
1245+
12161246
return LanZouCloud.SUCCESS
12171247

12181248
def down_dir_by_id(self, folder_id, save_path='./Download', *, callback=None, mkdir=True, overwrite=False,
1219-
failed_callback=None, downloaded_handler=None) -> int:
1249+
failed_callback=None, downloaded_handler=None, recursive=False) -> int:
12201250
"""登录用户通过id下载文件夹"""
12211251
file_list = self.get_file_list(folder_id)
12221252
if len(file_list) == 0:
@@ -1245,4 +1275,12 @@ def down_dir_by_id(self, folder_id, save_path='./Download', *, callback=None, mk
12451275
if failed_callback is not None:
12461276
failed_callback(code, file)
12471277

1278+
if recursive:
1279+
sub_folders = self.get_dir_list(folder_id)
1280+
if len(sub_folders) != 0:
1281+
for sub_folder in sub_folders:
1282+
self.down_dir_by_id(sub_folder.id, save_path, callback=callback, overwrite=overwrite,
1283+
failed_callback=failed_callback, downloaded_handler=downloaded_handler,
1284+
recursive=True)
1285+
12481286
return LanZouCloud.SUCCESS

lanzou/api/types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,4 @@
1515
DirectUrlInfo = namedtuple('DirectUrlInfo', ['code', 'name', 'durl'])
1616
FolderInfo = namedtuple('Folder', ['name', 'id', 'pwd', 'time', 'desc', 'url'], defaults=('',) * 6)
1717
FileInFolder = namedtuple('FileInFolder', ['name', 'time', 'size', 'type', 'url'], defaults=('',) * 5)
18-
FolderDetail = namedtuple('FolderDetail', ['code', 'folder', 'files'], defaults=(0, None, None))
18+
FolderDetail = namedtuple('FolderDetail', ['code', 'folder', 'files', 'sub_folders'], defaults=(0, None, None, None))

0 commit comments

Comments
 (0)