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

如何使用Python递归下载SharePoint指定PDF并回传原路径

问题需求
  • SharePoint指定路径下每日自动生成若干名称不固定的子文件夹,每个子文件夹内存储1个PDF文件
  • 递归遍历目标路径下所有子文件夹,跳过名称为Archive和Completed的子文件夹
  • 将其余子文件夹内的所有PDF文件下载到本地指定目录
  • 本地完成PDF内容分析后,将处理后的文件回传上传到SharePoint对应的原始子文件夹
现有代码问题
  • 未做文件格式筛选,会下载路径下所有类型文件,无法仅提取PDF格式文件
  • 仅遍历了Dis_Out根目录下的直属文件,没有递归遍历嵌套子文件夹,也未实现指定文件夹的跳过逻辑
实现思路
  • 封装递归遍历函数,传入当前待遍历的SharePoint文件夹对象、本地对应存储路径、路径映射字典:遍历过程中遇到文件夹名属于跳过列表时直接终止该分支遍历,其余子文件夹继续递归深入
  • 遍历当前文件夹下的文件时,判断文件后缀是否为.pdf(做大小写兼容,匹配.PDF等大写后缀),仅对符合格式要求的文件执行下载操作
  • 下载时本地保持和SharePoint端一致的目录结构,同时记录「本地文件路径-远端所属文件夹路径」的映射关系,避免不同子文件夹下同名PDF互相覆盖,也为后续回传提供路径依据
  • 本地PDF处理完成后,遍历之前记录的路径映射,将每个处理后的文件上传到对应的SharePoint文件夹即可
参考实现代码
import os
from office365.sharepoint.client_context import ClientContext
from office365.runtime.auth.authentication_context import AuthenticationContext

# 基础配置 可根据实际情况修改
ONEDRIVE_BASE_URL = 'https://abc.sharepoint.com/'
ONEDRIVE_SITE = '/sites/glas'
REMOTE_ROOT_FOLDER = '/sites/glas/Shared Documents/Targeting/Bot_testing/Dis_Out/'
LOCAL_SAVE_ROOT = './sharepoint_pdfs'
SKIP_FOLDER_NAMES = {'Archive', 'Completed'}
USER_INFO = {
    'username': '你的SharePoint账号',
    'password': '你的SharePoint密码'
}

def init_sharepoint_context():
    """初始化SharePoint连接上下文"""
    ctx_auth = AuthenticationContext(url=ONEDRIVE_BASE_URL)
    ctx_auth.acquire_token_for_user(USER_INFO['username'], USER_INFO['password'])
    return ClientContext(f"{ONEDRIVE_BASE_URL}{ONEDRIVE_SITE}", ctx_auth)

def recursive_download_pdfs(current_remote_folder, local_current_path, file_path_mapper):
    """
    递归遍历远端文件夹 下载符合要求的PDF
    :param current_remote_folder: 当前遍历的远端文件夹对象
    :param local_current_path: 当前文件夹对应的本地存储路径
    :param file_path_mapper: 存储 本地文件路径:远端所属文件夹路径 的映射 用于后续回传
    """
    ctx = current_remote_folder.context
    # 加载当前文件夹下的子文件夹和文件列表
    ctx.load(current_remote_folder.folders)
    ctx.load(current_remote_folder.files)
    ctx.execute_query()

    # 创建本地对应目录
    os.makedirs(local_current_path, exist_ok=True)
    # 下载当前目录下所有PDF文件
    for remote_file in current_remote_folder.files:
        file_name = remote_file.properties['Name']
        # 筛选PDF文件 兼容大小写后缀
        if file_name.lower().endswith('.pdf'):
            local_file_abs_path = os.path.join(local_current_path, file_name)
            print(f"下载文件: {file_name} -> 本地路径: {local_file_abs_path}")
            with open(local_file_abs_path, 'wb') as local_f:
                remote_file.download(local_f).execute_query()
            # 记录路径映射
            file_path_mapper[local_file_abs_path] = current_remote_folder.serverRelativeUrl

    # 递归处理子文件夹 跳过指定名称的文件夹
    for sub_folder in current_remote_folder.folders:
        sub_folder_name = sub_folder.properties['Name']
        if sub_folder_name in SKIP_FOLDER_NAMES:
            print(f"跳过指定文件夹: {sub_folder_name}")
            continue
        local_sub_path = os.path.join(local_current_path, sub_folder_name)
        recursive_download_pdfs(sub_folder, local_sub_path, file_path_mapper)
    return file_path_mapper

def upload_processed_file(local_file_path, target_remote_folder_url):
    """将处理后的本地文件上传到指定远端文件夹"""
    ctx = init_sharepoint_context()
    target_folder = ctx.web.get_folder_by_server_relative_url(target_remote_folder_url)
    file_name = os.path.basename(local_file_path)
    with open(local_file_path, 'rb') as f:
        target_folder.upload_file(file_name, f.read()).execute_query()
    print(f"回传文件完成: {file_name} -> 远端路径: {target_remote_folder_url}")

if __name__ == '__main__':
    # 初始化连接 获取远端根目录
    ctx = init_sharepoint_context()
    remote_root = ctx.web.get_folder_by_server_relative_url(REMOTE_ROOT_FOLDER)
    ctx.load(remote_root)
    ctx.execute_query()

    # 执行PDF下载
    path_mapping = recursive_download_pdfs(remote_root, LOCAL_SAVE_ROOT, {})

    # -------------------------- 在此处插入你的PDF处理逻辑 --------------------------
    for local_pdf in path_mapping.keys():
        print(f"正在处理本地PDF文件: {local_pdf}")
        # 替换为你自己的PDF内容分析、修改逻辑 直接操作本地文件即可
        # process_pdf(local_pdf)
    # -----------------------------------------------------------------------------

    # 处理完成后批量回传文件
    for local_path, remote_folder_url in path_mapping.items():
        upload_processed_file(local_path, remote_folder_url)
注意事项
  • 代码默认在本地保留和SharePoint端完全一致的目录结构,避免不同子文件夹下同名PDF被覆盖
  • 文件夹跳过逻辑默认大小写敏感,如果你的环境中存在小写命名的archive/completed文件夹,可自行往SKIP_FOLDER_NAMES集合中添加对应值
  • 如果你的SharePoint环境不支持账号密码认证,可替换为客户端凭证认证方式,核心的遍历、下载、上传逻辑无需修改

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 16:54:42