使用 Python 从个人 OneDrive 下载文件

Download files from personal OneDrive using Python

我有一个 Python 脚本,它在 AWS EC2 Ubuntu 机器上定期 运行ning。

此脚本从一些文件中读取数据,有时会更改其中的数据。

我想从 OneDrive 下载这些文件,自行处理,然后将它们上传回 OneDrive。

我希望自动完成此操作,无需用户批准任何登录或凭据。我可以接受一次(即在第一个 运行 上批准登录),但其余的必须自动 运行,无需再次请求批准(当然,除非权限更改)。

最好的方法是什么?

我一直在阅读有关 Microsoft Graph 的文档 API,但我在身份验证部分遇到困难。我在 Azure AAD 中创建了一个应用程序,授予示例权限(用于测试)并创建了一个秘密凭证。

我做到了。我不确定这是否是最好的方法,但它现在正在工作。它每小时自动 运行ning 一次,我不需要触摸它。

我关注了https://docs.microsoft.com/en-gb/azure/active-directory/develop/v2-oauth2-auth-code-flow

上的信息

这就是我所做的。

Azure 门户

  • 创建一个应用程序。 Azure Active Directory -> 应用程序注册 -> 来自个人帐户的应用程序
  • 支持的帐户类型中,选择具有个人 Microsoft 帐户
  • 重定向 URI 中,选择 Public client/native。我们稍后会添加具体的 URI。
  • 在应用程序详细信息的 概述 部分,记下 应用程序(客户端)ID 。我们稍后会用到它。
  • 身份验证部分,点击添加平台并选择桌面+设备。你可以使用你自己的,我选择了建议的一个:https://login.microsoftonline.com/common/oauth2/nativeclient
  • API 权限 部分,您必须添加您的应用将使用的所有权限。我添加了 User.ReadFiles.ReadWriteoffline_accessoffline_access 是为了能够获得 刷​​新令牌 ,这对于保持应用程序 运行ning 至关重要不要求用户登录。
  • 我没有创建任何 CertificateSecret

网络

好像是第一次获得令牌,我们必须使用浏览器或模拟类似的东西。

一定有一种程序化的方法可以做到这一点,但我不知道该怎么做。我也考虑过为此使用 Selenium,但由于它只有一次,而且我的应用程序每小时都会请求令牌(保持令牌新鲜),所以我放弃了这个想法。

如果我们添加新权限,我们拥有的令牌将失效,我们必须重新执行此手动部分。

  • 打开浏览器并转到下面的 URL。使用您在 Azure 门户中设置的 ScopesRedirect URI

https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=your_app_client_id&response_type=code&redirect_uri=https%3A%2F%2Flogin.microsoftonline.com%2Fcommon%2Foauth2%2Fnativeclient&response_mode=query&scope=User.Read%20offline_access%20Files.ReadWrite

URL 会将您重定向 到您设置的重定向 URI,并带有 URL 中的代码=某事。复制 something.

  • 执行 POST 请求,类型为 FORM URL 已编码。为此,我使用了 https://reqbin.com/

端点https://login.microsoftonline.com/common/oauth2/v2.0/token

表格URL: grant_type=authorization_code&client_id=your_app_client_id&code=use_the_code_returned_on_previous_step

这将 return 一个访问令牌和一个刷新令牌。将刷新令牌存储在某处。我正在将它保存在一个文件中。

Python

# Build the POST parameters
params = {
          'grant_type': 'refresh_token', 
          'client_id': your_app_client_id,
          'refresh_token': refresh_token_that_you_got_in_the_previous_step
         }

response = requests.post('https://login.microsoftonline.com/common/oauth2/v2.0/token', data=params)

access_token = response.json()['access_token']
new_refresh_token = response.json()['refresh_token']

# ^ Save somewhere the new refresh token. 
# I just overwrite the file with the new one. 
# This new one will be used next time.

header = {'Authorization': 'Bearer ' + access_token}

# Download the file
response = requests.get('https://graph.microsoft.com/v1.0/me/drive/root:' +
                         PATH_TO_FILE + '/' + FILE_NAME + ':/content', headers=header)

# Save the file in the disk 
with open(file_name, 'wb') as file:
    file.write(response.content)

所以基本上,我总是更新刷新令牌。

我使用该刷新令牌调用令牌端点,API 为我提供了一个在当前会话期间使用的访问令牌和一个新的刷新令牌。

我下次 运行 程序时使用这个新的刷新令牌,依此类推。