You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python连接关联Teams的私人SharePoint下载文件遇认证问题求助

解决SharePoint私人站点文件下载的认证与脚本问题

尝试通过Python自动化下载关联Teams专业版群组的私人SharePoint站点中的全部文件,但每次调试脚本都会出现相同错误,怀疑是认证问题。参考GitHub示例编写的脚本无法实现需求,脚本如下:

import os
from shareplum import Site
from shareplum import Office365
from shareplum.site import Version


class SPInterface:
    """This is a class to interact with Sharepoint from Python"""

    def __init__(self, sharepoint_base_url, username, password):
        self.username = username
        self.password = password
        self.sharepoint_base_url = sharepoint_base_url
        self.authcookie = Office365(
            sharepoint_base_url, username=username, password=password
        ).GetCookies()

    def download_file_sharepoint(
        self, source_path, sink_path, filename, sharepoint_site
    ):
        site = Site(sharepoint_site, version=Version.v2016, authcookie=self.authcookie)
        full_source_path = os.path.join(source_path, filename)
        full_sink_path = os.path.join(sink_path, filename)
        print(full_source_path)
        print(full_sink_path)
        folder = site.Folder(source_path)
        for attempt in range(0, 3):
            try:
                output_file = open(full_sink_path, "wb")
                input_file = folder.get_file(filename)
                binary_format = bytearray(input_file)
                output_file.write(binary_format)
                output_file.close()
                print("Attempt #No: ", attempt)
                print(
                    "Downloaded file size is ",
                    round(os.path.getsize(full_sink_path) / 1024, 2),
                    " KB",
                )
            except Exception as e:
                if attempt < 2:
                    print("Try again!")
                    continue
                print("Error", e)
                raise e
            break


def main():
    # stars anonymize private datas
    sharepoint_base_url = r'https://*.sharepoint.com/'
    username = "*"
    password = "*"
    source_path = 'sites/*/Shared%20Documents/'
    sharepoint_site = r'https://*.sharepoint.com/sites/*/'
    sink_path = r'C:/Users/*'
    sp = SPInterface(sharepoint_base_url, username, password)
    sp.download_file_sharepoint(source_path, sink_path, sharepoint_site)


if __name__ == "__main__":
    main()

脚本中的核心问题

  1. 参数不匹配错误
    main函数调用download_file_sharepoint时,参数顺序与函数定义不符:函数需要source_path, sink_path, filename, sharepoint_site四个参数,但调用时仅传入三个,直接触发参数数量错误。

  2. 路径格式错误
    source_path中的Shared%20Documents是URL编码格式,shareplum的Folder方法需要传入实际文件夹名称(即Shared Documents),而非编码后的字符串,否则会无法识别目标文件夹。

  3. 认证方式局限性
    私人/Teams关联的SharePoint站点普遍启用现代认证(如MFA),shareplum原生的用户名密码认证不支持MFA场景,这是你遇到认证错误的核心原因。

  4. 缺少批量下载逻辑
    当前脚本仅支持单个文件下载,没有遍历文件夹及子文件夹、批量下载全部文件的逻辑,不符合你的需求。


修复方案

1. 改用应用权限认证(支持MFA场景)

在Azure AD中注册应用,获取以下信息:

  • 租户ID(Tenant ID)
  • 客户端ID(Client ID)
  • 客户端密钥(Client Secret)
    为应用授予Sites.Read.All(或针对目标站点的Sites.Selected)权限,然后使用msal库获取访问令牌。

2. 修复脚本并添加批量下载逻辑

以下是修复后的完整脚本:

import os
from shareplum import Site
from shareplum.site import Version
import msal

class SPInterface:
    def __init__(self, tenant_id, client_id, client_secret, sharepoint_site_url):
        self.sharepoint_site_url = sharepoint_site_url
        # 使用MSAL获取应用级访问令牌
        authority = f"https://login.microsoftonline.com/{tenant_id}"
        app = msal.ConfidentialClientApplication(
            client_id, authority=authority, client_credential=client_secret
        )
        scope = ["https://*.sharepoint.com/.default"]
        result = app.acquire_token_for_client(scopes=scope)
        if "access_token" not in result:
            raise Exception(f"认证失败: {result.get('error_description')}")
        self.token = result['access_token']
        # 通过令牌初始化站点对象
        self.site = Site(sharepoint_site_url, version=Version.v2016, token=self.token)

    def download_folder(self, sp_folder_path, local_folder_path):
        # 创建本地文件夹(不存在则自动创建)
        os.makedirs(local_folder_path, exist_ok=True)
        # 获取SharePoint目标文件夹对象
        sp_folder = self.site.Folder(sp_folder_path)
        
        # 下载当前文件夹内的所有文件
        for file in sp_folder.files:
            file_name = file['Name']
            local_file_path = os.path.join(local_folder_path, file_name)
            with open(local_file_path, "wb") as f:
                f.write(sp_folder.get_file(file_name))
            print(f"已下载: {local_file_path}")
        
        # 递归处理子文件夹(跳过SharePoint系统文件夹Forms)
        for sub_folder in sp_folder.folders:
            sub_folder_name = sub_folder['Name']
            if sub_folder_name == "Forms":
                continue
            sub_sp_path = f"{sp_folder_path}/{sub_folder_name}"
            sub_local_path = os.path.join(local_folder_path, sub_folder_name)
            self.download_folder(sub_sp_path, sub_local_path)

def main():
    # 替换为你的实际信息
    tenant_id = "你的租户ID"
    client_id = "你的应用客户端ID"
    client_secret = "你的应用客户端密钥"
    sharepoint_site_url = "https://xxx.sharepoint.com/sites/你的站点名"
    sp_folder_path = "Shared Documents"  # Teams关联站点的默认文档库路径
    local_folder_path = r"C:/Users/xxx/下载/SharePoint文件"

    try:
        sp = SPInterface(tenant_id, client_id, client_secret, sharepoint_site_url)
        sp.download_folder(sp_folder_path, local_folder_path)
        print("全部文件下载完成")
    except Exception as e:
        print(f"错误: {e}")

if __name__ == "__main__":
    main()

3. 关键说明

  • 认证逻辑:使用MSAL库获取应用级令牌,绕过MFA限制,完美适配私人/Teams关联的SharePoint站点。
  • 批量下载:递归遍历目标文件夹下的所有文件和子文件夹,自动同步本地目录结构。
  • 路径处理:使用实际文件夹名称(如Shared Documents)而非URL编码字符串,避免路径识别错误。

内容的提问来源于stack exchange,提问作者Grobln

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 07:57:52