【WebDav】坚果云使用WebDav访问文件夹内文档大于750份无法返回问题
坚果云分页多次加载解决办法
- 问题
- 坚果云使用WebDav访问限制
- 现象
- PropFind请求返回数据少于文件夹内数据
- 坚果云请求响应体
- 坚果云请求响应头
- 结论
- 文档遍历实现
- python循环方式实现
问题
坚果云使用WebDav访问限制
在批量请求时使用大部份的WebDav库请求坚果云时都会出现仅请求到前750条数据,当询问客服后得到回复是如下图所示限制:
现象
PropFind请求返回数据少于文件夹内数据
WebDav协议使用的请求是PropFind方法(释意如下):
主要用于获取指定资源的属性集合。它属于WebDAV(Web Distributed Authoring and Versioning)协议的一部分,允许客户端查询与给定资源相关的元数据、配置和状态信息。
坚果云请求响应体
若直接请求目录会仅返回750个文件,若文件数量超过750个无法再次返回
响应体(仅返回750个数据):
坚果云请求响应头
观察响应头(值得注意的是响应头中返回了一个link字段,该字段的值为一个链接):
使用PropFind方法再次访问此链接(链接需要通过url编码变换后进行访问,可以看出返回了另外750行数据):
结论
由上述现象可以发现,请求时若数据过多(超过750条)会在响应头中带上link字段(即下一组数据的访问链接),故多页多次加载最简单的实现方式仅需要使用递归请求(展平为循环请求)即可拿到文件夹内所有的数据。
- 1.QPM数限制:请求时注意请求次数限制1500/30min的请求次数,超过请求限制,需要等待解封获取数据时间变长。
- 2.按需请求:请求时应注意避免过度请求数据导致数据返回时间长,可计算后按需请求,例如仅需要文件夹内前850份数据单文件内有2800份数据,那仅需请求两次即可,无需请求四次拿到全量数据。
文档遍历实现
python循环方式实现
class DavClient: """ 默认:1500/30min """ def __init__(self, dav_url, username, password, req_frequency=100): auth_str = f'{username}:{password}' auth_bytes = auth_str.encode('ascii') auth_base = base64.b64encode(auth_bytes).decode('ascii') self.headers = {'Authorization': f'Basic {auth_base}'} self.dav_url = dav_url self.req_frequency = req_frequency def _req_data(self, step_url) -> tuple[str, str, str]: response = requests.request('PROPFIND', step_url, headers=self.headers, verify=False) # 获取响应头link及rel next_link = "" rel = '' if "Link" in response.headers: link_str = response.headers.get("Link") next_link, rel = re.findall(pattern="; rel=\"(.*)\"", string=link_str)[0] response.raise_for_status() return unquote(next_link), rel, response.text def _analysis_res_data(self, response_text): tree = ElementTree.fromstring(response_text) namespace = {'d': 'DAV:'} file_data_list = [{"fileName": response.find('.//d:displayname', namespace).text, "href": unquote(response.find('d:href', namespace).text)} for response in tree.findall('d:response', namespace)] return file_data_list def ls(self, path, detail: bool=False): """ QPM: 控制请求速率,防止失败 50qpm """ document_list = [] current_link = f'{self.dav_url}{path}' req_count = 0 std_qpm = self.req_frequency / 60 start_time = time.perf_counter() while current_link: end_time = time.perf_counter() delta_time = end_time - start_time print("QPM", std_qpm, req_count, delta_time, req_count / delta_time) if delta_time == 0 or (std_qpm > (req_count / delta_time)): req_count += 1 next_link, rel, res_text = self._req_data(step_url=current_link) current_link = next_link file_list = self._analysis_res_data(res_text) document_list.extend(file_list) else: print(f'停一下{req_count}') time.sleep(1) return document_list
- python循环方式实现
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。