如何在独立 Python 脚本中正确认证 Google

58 阅读2分钟

为了从 Gmail 联系人中提取电子邮件地址并将其保存到文本文件中,编写了一个简单的 Python 脚本,该脚本基于 Python gdata 库(当前版本为 2.0.18)运行在 cron 作业中。但在本月早些时候,由于 Google 不再支持 ClientLogin 协议,该脚本停止工作,错误信息如下:

{'status': 401, 'body': '<?xml version="1.0" encoding="UTF-8"?>\n<errors xmlns="http://schemas.google.com/g/2005">\n <error>\n  <domain>GData</domain>\n  <code>required</code>\n  <location type="header">Authorization</location>\n  <internalReason>Login Required</internalReason>\n </error>\n</errors>\n', 'reason': 'Unauthorized'}

过去曾处理过其他地方(如 App Engine 应用程序)的类似问题,但这次忘记了需要对脚本进行转换。现在发现不知道该如何让它工作。

找到的所有参考,如 Google Apps 开发者博客或 StackOverflow 上的链接,都建议使用 OAuth2Token。但是,这需要一个客户端 ID 和客户端密钥,这些密钥来自与应用程序绑定的 Google API 控制台。而我并没有一个应用程序,只想通过我的脚本进行认证。

是否有适当的方法可以在独立脚本中完成此操作?或者真的无法再完成此操作了?

以下是如何在 gdata 中使用 ClientLogin 的代码:

from gdata.contacts.service import ContactsService, ContactsQuery

user = "myuser@gmail.com"
password = "mypassword"

addresses = set()
client = ContactsService(additional_headers={"GData-Version":"2"})
client.ssl = True
client.ClientLogin(user, password)
groups = client.GetGroupsFeed()
for group in groups.entry:
   if group.content.text == "System Group: My Contacts":
      query = ContactsQuery()
      query.max_results = 9999   # large enough that we'll get "everything"
      query.group = group.id.text
      contacts = client.GetContactsFeed(query.ToUri())
      for contact in contacts.entry:
         for email in contact.email:
            addresses.add(email.address.lower())
      break
return addresses

希望可以找到其他方法来替换 client.ClientLogin(),同时保留使用 gdata 的其他部分。或者,如果无法使用 gdata 完成此操作,可以考虑转向其他提供类似功能的库。

2、解决方案

由于 gdata 库不再支持 ClientLogin 协议,需要使用 OAuth2 进行认证。

根据推荐,可以使用 OAuth2 设备流程,这对于独立脚本来说可能更简单。

以下是如何使用 OAuth2 设备流程进行认证的步骤:

  1. 创建一个 Cloud Developer 项目,并启用 Contacts API。
  2. 在 API 控制台中创建 OAuth2 凭据,并选择“其他”作为应用程序类型。
  3. 在脚本中使用 OAuth2Client 库,可以在此链接上找到库的文档:github.com/google/oaut…
  4. 使用 OAuth2Client 库中的 refresh_grant 来调用刷新令牌,以获取新的访问令牌。
  5. 将新的访问令牌传递给 gdata 库,以进行认证。

以下是如何使用 OAuth2Client 库进行认证的代码示例:

import oauth2client

# 创建 OAuth2 凭据
credentials = oauth2client.client.OAuth2Credentials(
    client_id="YOUR_CLIENT_ID",
    client_secret="YOUR_CLIENT_SECRET",
    refresh_token="YOUR_REFRESH_TOKEN"
)

# 刷新令牌以获取新的访问令牌
credentials.refresh(oauth2client.client.GoogleCredentials.get_application_default())

# 使用新的访问令牌对 gdata 库进行认证
client = ContactsService()
client.ssl = True
client.additional_headers['Authorization'] = f'Bearer {credentials.access_token}'

使用此方法,就可以在独立 Python 脚本中使用 gdata 库对 Google 进行认证,从而提取 Gmail 联系人中的电子邮件地址。