【WebDav】坚果云使用WebDav访问文件夹内文档大于750份无法返回问题

06-01 1203阅读

坚果云分页多次加载解决办法

  • 问题
    • 坚果云使用WebDav访问限制
    • 现象
      • PropFind请求返回数据少于文件夹内数据
      • 坚果云请求响应体
      • 坚果云请求响应头
      • 结论
      • 文档遍历实现
        • python循环方式实现

          问题

          坚果云使用WebDav访问限制

            在批量请求时使用大部份的WebDav库请求坚果云时都会出现仅请求到前750条数据,当询问客服后得到回复是如下图所示限制:

          【WebDav】坚果云使用WebDav访问文件夹内文档大于750份无法返回问题

          现象

          PropFind请求返回数据少于文件夹内数据

          WebDav协议使用的请求是PropFind方法(释意如下):

            主要用于获取指定资源的属性集合。它属于WebDAV(Web Distributed Authoring and Versioning)协议的一部分,允许客户端查询与给定资源相关的元数据、配置和状态信息‌。

          坚果云请求响应体

          若直接请求目录会仅返回750个文件,若文件数量超过750个无法再次返回

          响应体(仅返回750个数据):

          【WebDav】坚果云使用WebDav访问文件夹内文档大于750份无法返回问题

          坚果云请求响应头

          观察响应头(值得注意的是响应头中返回了一个link字段,该字段的值为一个链接):

          【WebDav】坚果云使用WebDav访问文件夹内文档大于750份无法返回问题

          使用PropFind方法再次访问此链接(链接需要通过url编码变换后进行访问,可以看出返回了另外750行数据):

          【WebDav】坚果云使用WebDav访问文件夹内文档大于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
            
免责声明:我们致力于保护作者版权,注重分享,被刊用文章因无法核实真实出处,未能及时与作者取得联系,或有版权异议的,请联系管理员,我们会立即处理! 部分文章是来自自研大数据AI进行生成,内容摘自(百度百科,百度知道,头条百科,中国民法典,刑法,牛津词典,新华词典,汉语词典,国家院校,科普平台)等数据,内容仅供学习参考,不准确地方联系删除处理! 图片声明:本站部分配图来自人工智能系统AI生成,觅知网授权图片,PxHere摄影无版权图库和百度,360,搜狗等多加搜索引擎自动关键词搜索配图,如有侵权的图片,请第一时间联系我们。

相关阅读

目录[+]

取消
微信二维码
微信二维码
支付宝二维码