第三方 API

Google Ads 脚本有一项强大功能,即能与数据整合 第三方 API 访问这些服务和服务。

本指南涵盖以下概念,可帮助您编写脚本以 连接到其他服务:

  • 发出 HTTP 请求:如何使用 使用UrlFetchApp即可访问 外部 API。
  • 身份验证:我们介绍了一些常见的身份验证场景。
  • 解析响应:如何处理返回的 JSON 和 XML 数据。

我们还加入 示例 介绍这些概念的热门 API。

使用 UrlFetchApp 提取数据

UrlFetchApp 提供 与第三方 API 交互所需的核心功能。

以下示例展示了如何从 OpenWeatherMap。我们选择 OpenWeatherMap 是因为 相对简单的授权方案和 API。

发出请求

OpenWeatherMap 文档详细说明了 用于请求当前天气信息的格式, 如下所示:

http://api.openweathermap.org/data/2.5/weather?q=[location]&apikey=[apikey]

该网址提供了我们的第一个授权示例:参数 apikey 是 且值对每个用户都是唯一的。该密钥通过 注册

注册后,可以按如下方式发出使用该密钥的请求:

const location = 'London,uk';
const apikey = 'da.......................81'; // Replace with your API key
const currentWeatherUrl = `http://api.openweathermap.org/data/2.5/weather?q=${location}&apiKey=${apiKey}`;
const response = UrlFetchApp.fetch(currentWeatherUrl);
console.log(response.getContentText());

执行此代码会产生一长串的 JSON 写入 Google Ads 脚本记录窗口中的文本。

下一步是将其转换为可在您的 脚本。

JSON 数据

许多 API 都以 JSON 格式提供响应。这表示 JavaScript 对象的序列化,例如对象、数组和基本类型 可以表示和传输为字符串。

转换 JSON 字符串(例如,从 OpenWeatherMap—返回 JavaScript 对象,使用内置的 JSON.parse 方法结合使用。接着上面的示例继续:

const json = response.getContentText();
const weatherData = JSON.parse(json);
console.log(weatherData.name);
//  "London"

JSON.parse 方法将字符串转换为对象,该对象具有属性 name

请参阅解析响应部分,详细了解 处理不同格式的 API 响应。

错误处理

在使用第三方 API 时,错误处理是一项重要的考虑因素 因为第三方 API 经常会频繁变动, 意外的响应值,例如:

  • 该 API 的网址或参数可能会在您不知情的情况下发生变化。
  • 您的 API 密钥(或其他用户凭据)可能会过期。
  • 响应的格式可能会发生变化,恕不另行通知。

HTTP 状态代码

由于有可能出现意外响应,您应该检查 HTTP 状态代码。默认情况下 如果遇到 HTTP 错误代码,UrlFetchApp 会抛出异常。接收者 更改此行为,则需要传递可选参数,如 示例:

const options = {
  muteHttpExceptions: true
}
const response = UrlFetchApp.fetch(url, options);
// Any status code greater or equal to 400 is either a client or server error.
if (response.getResponseCode() >= 400) {
  // Error encountered, send an email alert to the developer
  sendFailureEmail();
}

响应结构

当第三方 API 发生变化时,开发者通常不会立即意识到 可能会影响其脚本的更改例如,如果 name 属性 则更改为 locationName,脚本 将失败。

因此,测试返回的结构是否 符合预期,例如:

const weatherData = JSON.parse(json);
if (weatherData && weatherData.name) {
  console.log('Location is : ' + name);
} else {
  console.log('Data not in expected format');
}

使用 UrlFetchApp 使用 POST 数据

OpenWeatherMap 的入门示例 仅提取了数据。通常,不会更改遥控器状态的 API 调用 服务器使用 HTTP GET 方法。

GET 方法是 UrlFetchApp 的默认方法。但某些 API 调用 例如调用发送短信的服务,则需要其他方法, 例如 POSTPUT

为了说明如何通过 UrlFetchApp 调用 POST,以下示例 演示与 Slack(一种协作消息传递)的集成 应用,以向 Slack 用户和群组发送 Slack 消息。

设置 Slack

本指南假定您已注册 Slack 账号。

与上例中的 OpenWeatherMap 一样,您需要获取一个 令牌以启用消息发送功能。Slack 提供了一个唯一的网址,让您可以 向您的团队发送消息,称为“传入的网络钩子”。

设置传入的网络钩子,方法是点击 添加传入的 Webhook 集成,并按照说明操作。通过 进程应发出一个用于传递消息的网址。

发出 POST 请求

设置传入的网络钩子后,发出 POST 请求只需要 options 参数中使用了一些额外的属性, UrlFetchApp.fetch:

  • method:如前所述,此属性默认为 GET,但在这里我们会替换它, 请将其设置为 POST
  • payload:这是要作为 POST 的一部分发送到服务器的数据 请求。在此示例中,Slack 需要一个序列化为 JSON 格式的对象 如 Slack 文档。为此, JSON.stringify 方法,并且 Content-Type 设置为 application/json

      // Change the URL for the one issued to you from 'Setting up Slack'.
      const SLACK_URL = 'https://hooks.slack.com/services/AAAA/BBBB/CCCCCCCCCC';
      const slackMessage = {
        text: 'Hello, slack!'
      };
    
      const options = {
        method: 'POST',
        contentType: 'application/json',
        payload: JSON.stringify(slackMessage)
      };
      UrlFetchApp.fetch(SLACK_URL, options);
    

扩展的 Slack 示例

上面的示例展示了启用传入 Slack 消息的最低要求。一个 扩展示例展示了 制作并发送广告系列效果 报告至 以及一些格式设置和显示选项。

收到的消息

请参阅 Slack 中的消息格式设置 有关 Slack 消息的更多详细信息的文档。

表单数据

上面的示例演示了如何使用 JSON 字符串作为 payload 属性 用于 POST 请求。

根据 payload 的格式,UrlFetchApp 会采用不同的方法 构建 POST 请求:

  • payload 是字符串时,字符串参数会作为 请求的正文部分。
  • payload 是对象(例如值的映射)时:

    {to: 'mail@example.com', subject:'Test', body:'Hello, World!'}
    

    键值对将转换为表单数据:

    subject=Test&to=mail@example.com&body=Hello,+World!
    

    此外,该请求的 Content-Type 标头也设置为 application/x-www-form-urlencoded

有些 API 在提交 POST 请求时需要使用表单数据, 从 JavaScript 对象自动转换为表单数据非常有用, 。

HTTP 基本身份验证

HTTP 基本协议 Authentication 是 这是最简单的身份验证形式,被许多 API 采用。

身份验证的实现方式是将经过编码的用户名和密码附加到 每个请求中的 HTTP 标头。

HTTP 基本身份验证

构建请求

要生成经过身份验证的请求,您需要执行以下步骤:

  1. 将用户名和密码与 冒号,例如 username:password
  2. 对口令进行 Base64 编码,例如将 username:password 转换为 dXNlcm5hbWU6cGFzc3dvcmQ=
  3. Authorization 标头附加到请求中,格式为 Authorization: Basic <encoded passphrase>

以下代码段说明了如何使用 Google Ads 脚本来实现此目的:

const USERNAME = 'your_username';
const PASSWORD = 'your_password';
const API_URL = 'http://<place_api_url_here>';

const authHeader = 'Basic ' + Utilities.base64Encode(USERNAME + ':' + PASSWORD);
const options = {
  headers: {Authorization: authHeader}
}
// Include 'options' object in every request
const response = UrlFetchApp.fetch(API_URL, options);

基本身份验证示例

代码示例 部分包含两个说明如何使用 HTTP 基本身份验证的示例:

Plivo

Plivo 是一项服务,方便您发送和 接收短信。此示例展示了如何 消息。

  1. Plivo 注册。
  2. 示例脚本粘贴到 在 Google Ads 中创建一个新脚本。
  3. PLIVO_ACCOUNT_AUTHIDPLIVO_ACCOUNT_AUTHTOKEN 值替换为 值。
  4. 按照脚本中指定的方式插入您的电子邮件地址,以接收 的通知 错误。
  5. 如要使用 Plivo,您必须购买号码或在试用中添加号码 。添加沙盒编号 试用账号。
  6. 将显示为发送者的号码和接收者都添加 数字。
  7. 将脚本中的 PLIVO_SRC_PHONE_NUMBER 更新为其中一个沙盒编号 刚刚注册过。这应包含国际国家/地区代码, 447777123456 表示英国号码。

Twilio

Twilio 是另一项服务, 接收短信。此示例展示了如何 消息。

  1. Twillio 注册。
  2. 粘贴示例脚本 转换为新脚本。
  3. TWILIO_ACCOUNT_SIDTWILIO_ACCOUNT_AUTHTOKEN 值替换为 账号控制台页面上显示的所有值。
  4. TWILIO_SRC_PHONE_NUMBER 替换为 信息中心,这就是 Twilio 授权的号码发送消息。

OAuth 1.0

许多热门服务都使用 OAuth 进行身份验证。OAuth 具有多种 变种和版本

而使用HTTP 基本身份验证时,用户 只有一个用户名和密码,OAuth 允许第三方应用 通过特定于该账号的凭据访问用户的账号和数据, 第三方应用程序。此外,访问范围也将 该应用的专用 IP 地址

如需了解 OAuth 1.0 的背景信息,请参阅 OAuth Core 指南。 请特别留意 6.使用 OAuth 进行身份验证。全能三足式 OAuth 1.0,流程如下:

  1. 应用(“使用方”)获取请求令牌。
  2. 由用户向请求令牌授权。
  3. 应用使用请求令牌交换访问令牌。
  4. 对于所有后续资源请求,访问令牌将用于已签名的 请求。

让第三方服务在无需用户互动的情况下使用 OAuth 1.0(例如 ,因为 Google Ads 脚本要求执行)步骤 1、2 和 3。 因此,有些服务会通过其配置颁发访问令牌 控制台,让应用可以直接转到第 4 步。这称为 单方模式 OAuth 1.0

OAuth1

Google Ads 脚本中的 OAuth 1.0

对于 Google Ads 脚本,每个脚本通常被解释为一个应用。 通过该服务的控制台/管理设置页面,通常可以 必须执行以下操作:

  • 设置应用配置,以表示脚本。
  • 指定要扩展至脚本的权限。
  • 获取使用方密钥、使用方密钥、访问令牌和访问密钥以供使用 使用单方模式 OAuth 进行身份验证

OAuth 2.0

OAuth 2.0用于常用的 API 用户数据指定第三方服务授权的账号所有者 权限,以允许它们访问用户数据。通过 优点是所有者:

  • 无需与应用共享其账号凭据。
  • 可以控制哪些应用有权访问这些数据,以及 什么程度的。(例如,授予的访问权限可能是只读的,也可能仅对 数据的子集。)

要在 Google Ads 脚本中使用启用了 OAuth 2.0 的服务,需要遵循以下几种方法: 步骤:

脚本之外

授权 Google Ads 脚本通过 第三方 API。在大多数情况下,这需要设置一个 application 位于该第三方服务的控制台中。此申请 代表您的 Google Ads 脚本。

您需要指定 Google Ads 脚本应用应具备的访问权限 客户 ID,通常会获得一个客户 ID。这样,您就可以 使用 OAuth 2 来控制哪些应用 以及他们可以看到或查看这些数据的哪些方面 修改。

在您的脚本中

使用远程服务器进行授权。根据授权类型, 但需要一系列不同的步骤(称为“流程”) 但所有操作最终都会导致生成访问令牌 将用于该会话的所有后续请求。

发出 API 请求。随每个请求传递访问令牌

授权流程

每种授权类型和相应的流程都适合不同的使用场景。对于 例如,当用户参与互动 这与需要在会话中运行应用的情况不同 在没有用户呈现的情况下显示背景

API 提供方将决定他们接受哪些授权类型,并以此为指导 用户继续集成其 API 的方式

实现

对于所有不同的 OAuth 流程,我们的目标是获得一个访问令牌, 可用于在会话的剩余时间内对请求进行身份验证。

示例库 说明了如何针对每种不同的流程类型进行身份验证。以上每一个 方法会返回一个对象,用于获取并存储访问令牌;以及 为经过身份验证的请求提供便利。

常规使用模式如下:

// Authenticate using chosen flow type
const urlFetchObj = OAuth2.<flow method>(args);
// Make request(s) using obtained object.
const response1 = urlFetchObj.fetch(url1);
const response2 = urlFetchObj.fetch(url2, options);

客户端凭据授权

客户端凭据授权 其中一种较简单的 OAuth2 流程形式,在这种流程中,应用会交换 是应用独有的 ID 和密钥, 有时间限制的访问令牌

客户端凭据

// Access token is obtained and cached.
const authUrlFetch = OAuth2.withClientCredentials(
    tokenUrl, clientId, clientSecret, optionalScope));
// Use access token in each request
const response = authUrlFetch.fetch(url);
// ... use response

刷新令牌授权

刷新令牌授权与客户端凭据授权类似, 只要向服务器发出简单请求,系统就会返回一个访问令牌,该令牌可用于 。

刷新令牌

获取刷新令牌

与刷新令牌授权的区别在于 从应用配置授予客户端凭据的权限 (例如,在服务的控制台中)授予刷新令牌 (例如授权代码) 授权,这要求用户 互动:

授权代码

使用 OAuth 园地获取刷新令牌

OAuth2 Playground 提供了一个界面,让用户能够 可逐步完成授权代码授权操作,以获取刷新令牌。

通过右上角的“设置”按钮,您可以定义 包括:

  • 授权端点:用作授权流程的开始。
  • 令牌端点:与刷新令牌配合使用以获取访问令牌。
  • 客户端 ID 和密钥:应用的凭据。

OAuth Playground

使用脚本获取刷新令牌

为完成该流程,我们提供了基于脚本的替代方案, 刷新令牌 第几代 示例。

刷新令牌用量

完成初始授权后,服务可以发出刷新 令牌,可以按与客户端凭据流程类似的方式使用。 下面给出了两个示例:

const authUrlFetch = OAuth2.withRefreshToken(tokenUrl, clientId, clientSecret,
    refreshToken, optionalScope);
const response = authUrlFetch.fetch(url);
// ... use response

Search Ads 360 示例

Search Ads 360 就是一个可与刷新令牌搭配使用的 API 示例。 在此示例中,脚本生成并返回 报告。请查阅搜索广告 360 API 参考文档。 可以执行的

创建脚本
  1. API 控制台中创建一个新项目。 并获取客户端 ID、客户端密钥和刷新令牌,请按照 操作步骤 请务必启用 DoubleClick Search API。
  2. 粘贴示例 脚本转换为 新脚本。
  3. 粘贴示例 OAuth2 库下方 代码清单。
  4. 修改脚本,使之包含正确的客户端 ID、客户端密钥 和刷新令牌

Apps Script Execution API 示例

此示例说明了如何使用应用 Script Execution API。这样,Apps 脚本 需要从 Google Ads 脚本中调用。

创建 Apps 脚本脚本

创建新脚本。以下示例将列出 10 个文件来自云端硬盘:

function listFiles() {
  const limit = 10;
  const files = [];
  const fileIterator = DriveApp.getFiles();
  while (fileIterator.hasNext() && limit) {
    files.push(fileIterator.next().getName());
    limit--;
  }
  return files;
}
配置要执行的 Apps 脚本
  1. 保存脚本。
  2. 点击资源 >Cloud Platform 项目
  3. 点击项目名称,前往 API 控制台。
  4. 转到 API 和服务
  5. 启用相应的 API,在本例中为云端硬盘 API应用 脚本执行 API
  6. 从菜单中的凭据项创建 OAuth 凭据。
  7. 返回到您的脚本,点击发布 > 部署为 API 可执行文件
创建 Google Ads 脚本
  1. 粘贴示例 脚本转换为 在 Google Ads 中创建一个新脚本。
  2. 此外,请将示例 OAuth2 库下方 代码清单。
  3. 修改脚本,使之包含正确的客户端 ID、客户端密钥 和刷新令牌

服务账号

上述授权类型的替代方法是使用服务 账号

服务账号与上述账号的不同之处在于它们不用于访问用户 数据:完成身份验证后,服务账号会代表 而不是拥有相应项目的用户。例如,如果 服务账号要使用 Drive API 创建文件 属于该服务账号,并且默认情况下, 项目所有者。

Google Natural Language API 示例

Natural Language API 提供 情感 分析实体 文本分析

此示例展示了如何计算 情感 。它衡量的是 以及具体质量: 我们销售蛋糕我们销售北京最好的蛋糕。立即购买!

设置脚本
  1. API 控制台中创建一个新项目
  2. 启用 Natural Language API
  3. 为项目启用结算功能。
  4. 创建 Service 账号。 下载凭据 JSON 文件。
  5. 粘贴示例 脚本转换成新的 脚本。
  6. 此外,请将示例 OAuth2 库下方 代码清单。
  7. 替换必要的值: <ph type="x-smartling-placeholder">
      </ph>
    • serviceAccount:服务账号的电子邮件地址,例如 xxxxx@yyyy.iam.gserviceaccount.com
    • key:创建 Service 时下载的 JSON 文件中的密钥 账号。开始时间为 -----BEGIN PRIVATE KEY...,结束时间为 ...END PRIVATE KEY-----\n

API 响应

API 可以返回各种格式的数据。其中最值得关注的是 XML 和 JSON。

JSON

JSON 通常比 XML 更容易处理 响应格式。不过,仍然可能出现一些问题。

回复验证

从对 API 的调用中获得成功响应后, 下一步是使用 JSON.parse 将 JSON 字符串转换为 JavaScript 对象。此时,处理解析 失败

const json = response.getContentText();
try {
  const data = JSON.parse(json);
  return data;
} catch(e) {
  // Parsing of JSON failed - handle error.
}

此外,如果此 API 不在您的控制之下,请考虑该 API 的结构 响应可能会更改,并且属性可能不再存在:

// Less good approach
// Assumes JSON was in form {"queryResponse": ...} when parsed.
const answer = data.queryResponse;

// Better approach
if (data && data.queryResponse) {
  const answer = data.queryResponse;
} else {
  // Format of API response has changed - alert developer or handle accordingly
}

XML

验证

XML 仍然是构建 API 的常用格式。来自 API 调用的响应 可以使用 XmlService parse 方法:

const responseText = response.getContentText();
try {
  const document = XmlService.parse(responseText);
} catch(e) {
  // Error in XML representation - handle accordingly.
}

XmlService.parse 会检测 XML 中的错误并抛出异常 因此,它不提供根据 架构。

根元素

如果 XML 文档成功解析,就会获取根元素 使用 getRootElement() 方法:

const document = XmlService.parse(responseText);
const rootElement = document.getRootElement();

命名空间

在以下示例中,Sportradar API 用于获取所选比赛的足球结果。XML 响应使用 以下格式:

<schedule xmlns="http://feed.elasticstats.com/schema/soccer/sr/v2/matches-schedule.xsd">
  <matches>
     ...
  </matches>
</schedule>

请注意如何在根元素中指定命名空间。因此, 必须执行以下操作:

  • 从文档中提取命名空间属性。
  • 在遍历和访问子元素时使用此命名空间。

以下示例展示了如何访问上述示例中的 <matches> 元素 文档片段:

const document = XmlService.parse(xmlText);
const scheduleElement = document.getRootElement();
// The namespace is required for accessing child elements in the schema.
const namespace = scheduleElement.getNamespace();
const matchesElement = scheduleElement.getChild('matches', namespace);

获取值

以橄榄球赛程的样本为例:

<match status="..." category="..." ... >
  ...
</match>

可以检索属性,例如:

const status = matchElement.getAttribute('status').getValue();

元素中包含的文本可以使用 getText() 进行读取, 在一个元素有多个文本子项的位置进行串联。考虑 如果有多个子项,请使用 getChildren() 进行迭代 概率。

Sportradar 示例

这款完整的 Sportradar 示例说明了 检索足球比赛详情,特别是英超 匹配。Soccer API 是 Sportradar 提供的众多体育信息流之一。

设置 Sportradar 账号
  1. 前往 Sportradar 开发者网站
  2. 注册试用账号
  3. 注册完成后,登录您的账号。
  4. 登录后,转到MyAccount

Sportradar 将不同的体育赛事划分为不同的 API。例如,您 可能会购买 Soccer API 的访问权限,而不是 Tennis API 的访问权限。每个 您创建的应用可关联不同的体育赛事,以及 不同的键。

  1. 在“Applications”(应用)下,点击 Create a new Application(创建新应用)。提供应用 名称和说明,并忽略网站字段。
  2. 仅选择 Issue a new key for Soccer Trial Europe v2(为欧洲足球试用版 v2 发放新密钥)。
  3. 点击注册应用

成功后,您应该会看到一个显示新 API 密钥的页面。

  1. 粘贴示例脚本 转换为新脚本。
  2. 将列表中的 API 密钥替换为上面获取的密钥,然后修改 电子邮件地址字段。

问题排查

使用第三方 API 时,错误可能是由多种原因造成的,例如, 示例:

  • 客户端以 API 不支持的格式向服务器发出请求。
  • 客户端需要的响应格式与所遇到的格式不同。
  • 使用无效令牌/键或值留作占位符的客户端。
  • 客户端达到用量限额。
  • 客户端提供无效参数。

在上述所有情况下以及其他所有情况中,确定根本原因 检查导致错误的响应的详细信息。

解析响应

默认情况下,任何返回错误的响应(状态 (例如代码400 或更多) 由 Google Ads 脚本引擎抛出。

为了防止此行为,并让系统能够正常显示 请将可选参数的 muteHttpExceptions 属性设置为 UrlFetchApp.fetch。例如:

const params = {
  muteHttpExceptions: true
};
const response = UrlFetchApp.fetch(url, params);
if (response.getResponseCode() >= 400) {
  // ... inspect error details...
}

常见状态代码

  • 200 OK 表示成功。如果响应不包含预期的 请考虑以下要点:

    • 有些 API 允许指定 。如需了解详情,请参阅 API 文档。
    • 一个 API 可以有多个可调用的资源。请查阅 以判断是否还有其他资源 并返回您所需的数据
    • 自编写代码以来,API 可能已更改。请查阅 文档或向开发者解释说明。
  • 400 Bad Request 通常表示 发送到服务器的请求的格式或结构。检查 请求并将其与 API 规范进行比较,以确保其符合 预期。请参阅检查请求,详细了解 如何检查请求

  • 401 Unauthorized 通常表示在调用 API 时没有提供或 已成功执行授权。

    • 如果 API 使用基本授权,请确保使用 Authorization 标头 在请求中构建和提供。
    • 如果 API 使用 OAuth 2.0,请确保已获取访问令牌 并且作为不记名令牌提供。
    • 对于授权的任何其他变体,请确保 请求的凭据。
  • 403 Forbidden 表示用户无权使用相应资源 请求。

    • 确保用户已被授予必要的权限,例如, 在基于文件的请求中,授予用户对某个文件的访问权限。
  • 404 Not Found 表示请求的资源不存在。

    • 检查用于 API 端点的网址是否正确。
    • 如果要提取资源,请检查正在引用的资源是否存在 (例如,如果基于文件的 API 存在相应文件)。

检查请求

当 API 响应表明请求质量不佳时,检查请求非常有用 格式,例如 400 状态代码。为帮助检查请求,UrlFetchApp 具有 fetch() 方法的配套方法,称为 getRequest()

此方法不会向服务器发送请求,而是会构建请求, 本应已发送,然后返回。这样,用户就可以 检查请求的元素,确保请求看起来正确无误。

例如,如果请求中的表单数据由串联的多个字符串组成, 那么错误可能就出在您创建的用于生成该表单的函数中, 数据。简单来说:

const request = UrlFetchApp.getRequest(url, params);
console.log(request);
// Now make the fetch:
const response = UrlFetchApp.fetch(url, params);
// ...

这样你就可以检查请求的元素

记录请求和响应

协助整个检查请求和响应的 第三方 API,则以下辅助函数可用作 替代 UrlFetchApp.fetch(),用于记录请求和响应。

  1. 将代码中的所有 UrlFetchApp.fetch() 实例替换为 logUrlFetch()

  2. 将以下函数添加到脚本的末尾。

    function logUrlFetch(url, opt_params) {
      const params = opt_params || {};
      params.muteHttpExceptions = true;
      const request = UrlFetchApp.getRequest(url, params);
      console.log('Request:       >>> ' + JSON.stringify(request));
      const response = UrlFetchApp.fetch(url, params);
      console.log('Response Code: <<< ' + response.getResponseCode());
      console.log('Response text: <<< ' + response.getContentText());
      if (response.getResponseCode() >= 400) {
        throw Error('Error in response: ' + response);
      }
      return response;
    }
    

执行脚本时,系统会将所有请求和响应的详细信息记录到 从而更轻松地进行调试。