> ## Documentation Index
> Fetch the complete documentation index at: https://docs.brightdata.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 将抓取结果投递到 webhook 与 S3

> 任务完成后将 Bright Data Scraper API 结果推送到 HTTPS webhook 或 Amazon S3 存储桶。涵盖触发参数、IAM 配置与 14 个 webhook 源 IP。

Bright Data Scraper API 任务可将结果直接推送到您的基础设施，无需等待您手动下载。添加 `endpoint` 参数即可使用 webhook 投递，或一次性配置云端目标，让每个任务自动写入。所有抓取器的配置方式完全相同，只有 `dataset_id` 不同。

<Tip>
  示例使用 LinkedIn 个人资料抓取器（`gd_l1viktl72bvl7bjuj0`）。请从[异步请求页的对照表](/cn/products/scrapers/scrapers-library/async-requests#我应该使用哪个-dataset-id)中替换为您所用平台的 `dataset_id`。
</Tip>

## 先决条件

* 拥有有效 API 密钥的 [Bright Data 账户](https://www.bright.cn/cp/start)
* 熟悉[异步请求流程](/cn/products/scrapers/scrapers-library/async-requests)
* 使用 webhook 时，需要一个可公开访问的 HTTPS 端点（或 [webhook.site](https://webhook.site) 等测试工具）
* 使用 S3 时，需要一个 Amazon S3 存储桶以及创建 IAM 角色的权限

## 我应该选择哪种投递方式？

| 方式                                        | 适用场景                | 配置                                                                       |
| :---------------------------------------- | :------------------ | :----------------------------------------------------------------------- |
| Webhook                                   | 事件驱动的数据管道，负载小于 1 GB | 一个查询参数，无需配置                                                              |
| Amazon S3                                 | 大体积负载、数据湖、长期留存      | 一次性配置 IAM 角色，之后自动投递                                                      |
| Google Cloud Storage、Azure、Snowflake、SFTP | 已有的云数据平台            | 一次性配置凭据，见[投递选项](/cn/products/scrapers/scrapers-library/delivery-options) |

## 如何将结果投递到 webhook

当您在触发异步采集时提供 `endpoint` URL，任务完成后 Bright Data 会向该 URL 发送包含抓取数据的 `POST` 请求，无需轮询。

```text theme={null}
您的应用 --> POST /trigger（带 webhook URL）--> Bright Data 抓取 --> POST 到您的 webhook
```

### 步骤 1：设置测试 webhook

测试时，可使用 [webhook.site](https://webhook.site) 获取临时公开 URL：

1. 在浏览器中打开 [webhook.site](https://webhook.site)
2. 复制页面显示的专属 URL（例如 `https://webhook.site/abc-123-def`）
3. 保持页面开启以监控收到的请求

### 步骤 2：使用 webhook URL 触发采集

在异步 `/trigger` 请求中添加 `endpoint` 查询参数：

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST \
    "https://api.brightdata.com/datasets/v3/trigger?dataset_id=gd_l1viktl72bvl7bjuj0&format=json&endpoint=https://webhook.site/abc-123-def&uncompressed_webhook=true" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -H "Content-Type: application/json" \
    -d '[
      {"url": "https://www.linkedin.com/in/satyanadella"},
      {"url": "https://www.linkedin.com/in/jeffweiner08"}
    ]'
  ```

  ```python Python theme={null}
  import requests

  WEBHOOK_URL = "https://webhook.site/abc-123-def"

  response = requests.post(
      "https://api.brightdata.com/datasets/v3/trigger",
      params={
          "dataset_id": "gd_l1viktl72bvl7bjuj0",
          "format": "json",
          "endpoint": WEBHOOK_URL,
          "uncompressed_webhook": "true",
      },
      headers={
          "Authorization": "Bearer YOUR_API_KEY",
          "Content-Type": "application/json",
      },
      json=[
          {"url": "https://www.linkedin.com/in/satyanadella"},
          {"url": "https://www.linkedin.com/in/jeffweiner08"},
      ],
  )

  print("Snapshot ID:", response.json()["snapshot_id"])
  ```

  ```javascript Node.js theme={null}
  const WEBHOOK_URL = "https://webhook.site/abc-123-def";

  const response = await fetch(
    `https://api.brightdata.com/datasets/v3/trigger?dataset_id=gd_l1viktl72bvl7bjuj0&format=json&endpoint=${encodeURIComponent(WEBHOOK_URL)}&uncompressed_webhook=true`,
    {
      method: "POST",
      headers: {
        "Authorization": "Bearer YOUR_API_KEY",
        "Content-Type": "application/json",
      },
      body: JSON.stringify([
        { url: "https://www.linkedin.com/in/satyanadella" },
        { url: "https://www.linkedin.com/in/jeffweiner08" },
      ]),
    }
  );

  const data = await response.json();
  console.log("Snapshot ID:", data.snapshot_id);
  ```
</CodeGroup>

关键参数：

| 参数                     | 说明                               |
| :--------------------- | :------------------------------- |
| `endpoint`             | 接收 `POST` 负载的 HTTP 端点 URL        |
| `uncompressed_webhook` | 设为 `true` 可接收未压缩的 JSON（默认为 gzip） |
| `format`               | 输出格式：`json`、`ndjson` 或 `csv`     |

### 步骤 3：验证投递

采集完成后（少量记录通常需 30 到 60 秒），查看您的 webhook.site 页面，应能看到一条包含抓取数据的 `POST` 请求。

该负载与直接通过 API 下载得到的 JSON 数组相同：

```json theme={null}
[
  {
    "name": "Satya Nadella",
    "city": "Redmond",
    "country_code": "US",
    "current_company": { "name": "Microsoft" },
    "followers": 10842560
  },
  {
    "name": "Jeff Weiner",
    "city": "San Francisco Bay Area",
    "country_code": "US",
    "current_company": { "name": "Next Chapter" },
    "followers": 1200000
  }
]
```

### 如何在生产环境中处理 webhook

在生产环境中，请将 `endpoint` URL 指向您自己的服务器端点。

```javascript server.js theme={null}
const express = require("express");
const app = express();

app.use(express.json({ limit: "100mb" }));

app.post("/webhook/scraper", (req, res) => {
  const records = req.body;
  console.log(`Received ${records.length} records`);

  for (const record of records) {
    console.log(`- ${record.name}`);
  }

  res.status(200).json({ received: true });
});

app.listen(3000, () => console.log("Webhook server running on port 3000"));
```

```python server.py theme={null}
from flask import Flask, request, jsonify

app = Flask(__name__)

@app.route("/webhook/scraper", methods=["POST"])
def handle_webhook():
    records = request.get_json()
    print(f"Received {len(records)} records")

    for record in records:
        print(f"- {record['name']}")

    return jsonify({"received": True}), 200

if __name__ == "__main__":
    app.run(port=3000)
```

<Warning>
  请在 30 秒内返回 `200` 状态码以确认接收。如果您的端点失败或超时，Bright Data 会重试投递。
</Warning>

### 如何为 webhook 投递添加鉴权

如果您的端点需要鉴权，请添加 `webhook_header_Authorization` 参数：

```bash theme={null}
curl -X POST \
  "https://api.brightdata.com/datasets/v3/trigger?dataset_id=gd_l1viktl72bvl7bjuj0&format=json&endpoint=https://your-server.com/webhook&webhook_header_Authorization=Bearer+YOUR_SECRET_TOKEN" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"url": "https://www.linkedin.com/in/satyanadella"}]'
```

### webhook 来自哪些 IP？

如果您的服务器使用 IP 允许列表，请添加以下 14 个 Bright Data webhook 源 IP：

```text theme={null}
54.175.27.69
34.225.9.175
100.28.38.247
100.29.18.195
52.72.185.255
35.174.112.248
54.165.183.124
3.91.140.7
52.202.75.37
98.82.225.117
100.27.150.189
18.214.10.85
35.169.71.210
44.194.183.74
```

## 如何将结果投递到 Amazon S3

S3 投递在控制面板中按抓取器一次性配置。配置完成后，每个任务都会自动将结果写入您的存储桶。

### 步骤 1：创建 IAM 角色

Bright Data 通过在您的 AWS 账户中扮演角色来写入存储桶。请创建一个信任 Bright Data 账户 `422310177405` 的角色，将您的 Bright Data 客户 ID 作为外部 ID，并授予该角色对存储桶的 `s3:PutObject` 权限。

完整的策略与信任关系 JSON 见[投递选项](/cn/products/scrapers/scrapers-library/delivery-options#aws-s3-user-role-permissions)。

### 步骤 2：配置投递目标

1. 进入您的[抓取器配置页](https://www.bright.cn/cp/scrapers)
2. 点击 **Delivery settings** 标签页
3. 选择 **Amazon S3** 作为投递目标
4. 填写您的凭据：
   * **Bucket name**：您的 S3 存储桶名称
   * **Role ARN**：步骤 1 中创建的 IAM 角色 ARN
   * **Region**：您的 S3 存储桶所在区域
   * **Path prefix**（可选）：存储桶内的文件夹路径（例如 `linkedin/profiles/`）
5. 选择所需的文件格式（JSON、NDJSON 或 CSV）
6. 点击 **Save**

### 步骤 3：触发采集

按常规方式触发异步采集，无需额外参数，结果会自动投递到您的 S3 存储桶：

```bash theme={null}
curl -X POST \
  "https://api.brightdata.com/datasets/v3/trigger?dataset_id=gd_l1viktl72bvl7bjuj0&format=json" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[
    {"url": "https://www.linkedin.com/in/satyanadella"},
    {"url": "https://www.linkedin.com/in/jeffweiner08"},
    {"url": "https://www.linkedin.com/in/rbranson"}
  ]'
```

### 步骤 4：验证投递

采集完成后，检查您的 S3 存储桶中是否已生成文件：

```bash theme={null}
aws s3 ls s3://your-bucket-name/linkedin/profiles/
```

您应能看到以快照 ID 命名的文件（例如 `s_m1a2b3c4d5e6f7g8h.json`）。下载并查看：

```bash theme={null}
aws s3 cp s3://your-bucket-name/linkedin/profiles/s_m1a2b3c4d5e6f7g8h.json ./results.json
cat results.json | python -m json.tool | head -20
```

您也可以使用 [Monitor Delivery API](/cn/api-reference/scrapers/management-apis/monitor-delivery) 查看投递状态。

## 故障排除

<Accordion title="Webhook 收不到数据？">
  * 确认该 URL 可公开访问（不能是 `localhost`）
  * 确认您的端点在 30 秒内返回 `200` 状态码
  * 如果有防火墙规则，请确认上述 14 个 webhook IP 已加入允许列表
</Accordion>

<Accordion title="收到的是压缩数据？">
  若省略 `uncompressed_webhook=true`，数据将以 gzip 压缩形式送达。请在触发 URL 中添加 `uncompressed_webhook=true`，或在服务器端解压负载。
</Accordion>

<Accordion title="负载超出服务器处理能力？">
  大型采集的负载最高可达 1 GB。请在 Express.js 中设置 `express.json({ limit: "100mb" })`，或在您所用框架中做等效配置。对于超大数据集，请改用 S3 投递。
</Accordion>

<Accordion title="S3 中没有出现文件？">
  * 确认 IAM 角色 ARN 和外部 ID 正确
  * 确认存储桶策略允许来自 Bright Data 账户的 `s3:PutObject`
  * 确认存储桶区域与配置一致
  * 在 Bright Data 控制面板的 **Logs** 中查看投递状态
</Accordion>

<Accordion title="S3 出现 Access denied 错误？">
  请确认 IAM 角色的信任策略包含 Bright Data 账户（`422310177405`），且外部 ID 与您的 Bright Data 客户 ID 一致，可在[账户设置](https://www.bright.cn/cp/setting/customer_details)中查看。
</Accordion>

## 常见问题

### 各平台的投递配置有区别吗？

没有区别。所有 Bright Data 抓取器的 webhook 参数和云端目标配置完全相同，只有触发请求中的 `dataset_id` 不同。

### 可以同时使用 webhook 和云存储吗？

可以。云端投递在控制面板中按抓取器配置，而 `endpoint` 参数按请求设置，因此单个任务可同时使用两者。

### 任务完成时我的 webhook 不可用会怎样？

Bright Data 会重试投递。如果您的端点持续不可用，可使用触发调用返回的 `snapshot_id` 直接下载快照，快照保留 30 天。

## 相关内容

* [异步请求](/cn/products/scrapers/scrapers-library/async-requests)
* [投递选项：GCS、Azure、Snowflake 与 SFTP](/cn/products/scrapers/scrapers-library/delivery-options)
* [流式与文件投递](/cn/products/scrapers/scrapers-library/stream-and-file-delivery)
