> ## 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.

# 将LinkedIn个人资料发送到您的CRM

> 构建一个端到端的管道，使用 Bright Data 抓取 LinkedIn 个人资料，并将 CRM 就绪的联系记录传递给部署在 Vercel 上的 Next.js webhook 处理程序。

你想要自动丰富入站线索。一份注册表单给你一个 LinkedIn 网址，一分钟后一条包含职位、公司、位置和粉丝数的联系人记录就会进入你的 CRM。无需手动复制粘贴，无需 Zapier 风格的胶水代码。

在本教程中，我们将端到端地构建该管道。你将部署一个微型 Next.js webhook 处理程序到 Vercel，对一些个人资料网址触发 Bright Data LinkedIn 爬虫 API，并在一分钟内观看映射的联系人记录出现在你的 Vercel 日志中。

我们在映射对象处停止。将其发送到特定 CRM 是我们将在最后概述的单行 fetch 调用。

## 你将构建什么

部署在 Vercel 上的 Next.js API 路由，其功能为：

1. 接收来自 Bright Data 的 POST，包含已爬取 LinkedIn 个人资料的 JSON 数组
2. 将每个个人资料映射到规范化的 CRM 形状的联系人记录
3. 记录映射的记录，以便你可以在 Vercel 仪表板中检查它们

然后你将从终端触发一次爬取，指向你部署的 Vercel URL，并看到两个个人资料被映射和记录，端到端。

**预计时间：** 25 分钟。

## 前置条件

* 一个 [Bright Data 账户](https://www.bright.cn/cp/start)，带有 API 密钥（[获取你的密钥](https://www.bright.cn/cp/setting/users)）
* 一个免费的 [Vercel 账户](https://vercel.com/signup)
* 本地安装的 Node.js 18+
* 已安装的 [Vercel CLI](https://vercel.com/docs/cli)：`npm install -g vercel`

## 第 1 部分：搭建 Next.js 项目

在新终端中，创建一个最小的 Next.js 项目：

```bash theme={null}
npx create-next-app@latest linkedin-to-crm
```

接受所有默认值。你将获得一个工作的 Next.js 14+ 项目，带有 App Router。然后进入它：

```bash theme={null}
cd linkedin-to-crm
```

## 第 2 部分：添加 webhook 路由

创建文件 `app/api/webhook/linkedin/route.ts`：

```typescript app/api/webhook/linkedin/route.ts theme={null}
export async function POST(request: Request) {
  const profiles = await request.json();
  console.log(`Received ${profiles.length} profiles from Bright Data`);

  for (const profile of profiles) {
    console.log(`- ${profile.name} (${profile.position})`);
  }

  return Response.json({ received: profiles.length });
}
```

这就是整个接收器。Next.js App Router 将任何 `route.ts` 文件视为 API 端点，因此仅此文件就在部署后为你提供了一个工作的 `POST /api/webhook/linkedin` 路由。

## 第 3 部分：部署到 Vercel

从项目根目录：

```bash theme={null}
vercel
```

第一次运行会引导你完成登录和项目创建。接受默认值。一分钟后，你应该看到以以下内容结尾的输出：

```
Production: https://linkedin-to-crm-<hash>.vercel.app
```

复制该 URL。你的 webhook 端点是：

```
https://linkedin-to-crm-<hash>.vercel.app/api/webhook/linkedin
```

<Tip>
  在 [Vercel 仪表板](https://vercel.com/dashboard) 中打开你的项目，并保持 **Logs** 选项卡可见。当 Bright Data POST 到端点时，你的 `console.log` 输出将出现在那里。
</Tip>

## 第 4 部分：触发爬取

打开第二个终端并触发 Bright Data LinkedIn 爬虫，将其指向你的 Vercel URL：

```bash theme={null}
curl -X POST \
  "https://api.brightdata.com/datasets/v3/trigger?dataset_id=gd_l1viktl72bvl7bjuj0&format=json&uncompressed_webhook=true&endpoint=https://linkedin-to-crm-<hash>.vercel.app/api/webhook/linkedin" \
  -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"}
  ]'
```

将 `YOUR_API_KEY` 替换为你的 Bright Data API 密钥，将 `linkedin-to-crm-<hash>` 替换为你的实际 Vercel URL。

你应该立即看到如下响应：

```json theme={null}
{"snapshot_id":"sd_mntfn0zq7xj0zeay"}
```

爬取以异步方式运行。你无需对 `snapshot_id` 执行任何操作。Bright Data 在作业完成时将结果 POST 到你的 Vercel 端点。对于两个个人资料，这通常需要 30 到 60 秒。

切换到 Vercel **Logs** 选项卡。一分钟内你应该会看到类似以下内容：

```
Received 2 profiles from Bright Data
- Satya Nadella (Chairman and CEO at Microsoft)
- Jeff Weiner (Executive Chairman at LinkedIn)
```

注意，两个个人资料在单个 POST 中到达。Bright Data 在一个请求中传递整个快照，而不是一次一个个人资料。

## 第 5 部分：将个人资料映射到 CRM 形状

现在处理程序仅记录名称和职位。真正的 CRM 期望具有特定字段名称的联系人记录：`full_name`、`job_title`、`company` 等。让我们将 Bright Data 有效负载规范化为该形状。

将 `app/api/webhook/linkedin/route.ts` 替换为：

```typescript app/api/webhook/linkedin/route.ts theme={null}
type BrightDataProfile = {
  name?: string;
  position?: string;
  current_company?: { name?: string };
  country_code?: string;
  city?: string;
  followers?: number;
  url: string;
};

type CrmContact = {
  full_name: string | null;
  job_title: string | null;
  company: string | null;
  country: string | null;
  city: string | null;
  linkedin_url: string;
  follower_count: number;
};

function mapToCrmContact(profile: BrightDataProfile): CrmContact {
  return {
    full_name: profile.name ?? null,
    job_title: profile.position ?? null,
    company: profile.current_company?.name ?? null,
    country: profile.country_code ?? null,
    city: profile.city ?? null,
    linkedin_url: profile.url,
    follower_count: profile.followers ?? 0,
  };
}

export async function POST(request: Request) {
  const profiles: BrightDataProfile[] = await request.json();
  console.log(`Received ${profiles.length} profiles from Bright Data`);

  const contacts = profiles.map(mapToCrmContact);

  for (const contact of contacts) {
    console.log(JSON.stringify(contact, null, 2));
  }

  // Next step: POST each contact to your CRM.
  // Example for HubSpot:
  //   await fetch("https://api.hubapi.com/crm/v3/objects/contacts", {
  //     method: "POST",
  //     headers: {
  //       Authorization: `Bearer ${process.env.HUBSPOT_TOKEN}`,
  //       "Content-Type": "application/json",
  //     },
  //     body: JSON.stringify({ properties: contact }),
  //   });

  return Response.json({ received: contacts.length });
}
```

重新部署：

```bash theme={null}
vercel --prod
```

重新运行第 4 部分中的相同 curl 命令。这次你的 Vercel 日志应该显示两个完整的映射联系人：

```json theme={null}
Received 2 profiles from Bright Data
{
  "full_name": "Satya Nadella",
  "job_title": "Chairman and CEO at Microsoft",
  "company": "Microsoft",
  "country": "US",
  "city": "Redmond",
  "linkedin_url": "https://www.linkedin.com/in/satyanadella",
  "follower_count": 10842560
}
{
  "full_name": "Jeff Weiner",
  "job_title": "Executive Chairman at LinkedIn",
  "company": "Next Chapter",
  "country": "US",
  "city": "San Francisco Bay Area",
  "linkedin_url": "https://www.linkedin.com/in/jeffweiner08",
  "follower_count": 1200000
}
```

该日志中的每个对象都是完整的 CRM 就绪联系人。将其发送到你的 CRM 是单个 fetch 调用。处理程序中注释掉的块概述了 HubSpot 版本。交换 Salesforce、Pipedrive 或你使用的任何工具的 URL 和标头。

## 保护 webhook

现在，任何猜到你的 Vercel URL 的人都可以向其 POST 假个人资料数据。在你将实时数据管道进实际 CRM 之前，锁定端点。

Bright Data 的触发调用接受 `webhook_header_Authorization` 查询参数，该参数被转发为 webhook POST 上的 `Authorization` 标头：

```bash theme={null}
curl -X POST \
  "https://api.brightdata.com/datasets/v3/trigger?dataset_id=gd_l1viktl72bvl7bjuj0&format=json&uncompressed_webhook=true&endpoint=https://linkedin-to-crm-<hash>.vercel.app/api/webhook/linkedin&webhook_header_Authorization=Bearer+YOUR_SHARED_SECRET" \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '[{"url": "https://www.linkedin.com/in/satyanadella"}]'
```

然后在处理程序中验证该标头，然后再处理：

```typescript theme={null}
export async function POST(request: Request) {
  const auth = request.headers.get("authorization");
  if (auth !== `Bearer ${process.env.WEBHOOK_SECRET}`) {
    return new Response("Unauthorized", { status: 401 });
  }

  const profiles = await request.json();
  // ...rest of the handler
}
```

在你的 Vercel 项目设置中将 `WEBHOOK_SECRET` 设置为环境变量，然后重新部署。

<Note>
  Bright Data 还发布了一个 webhook 源 IP 列表，你可以将其列入白名单。请参阅 webhook 参考中的 [Allowlist webhook IPs](/products/scrapers/scrapers-library/data-delivery#allowlist-webhook-ips)。
</Note>

## 恭喜

你已构建了一个端到端的管道，该管道爬取 LinkedIn 个人资料并向你自己的服务器提供 CRM 就绪的联系人记录：

* 部署在 Vercel 上的 **Next.js API 路由**，接收 Bright Data webhook
* 一个**映射器函数**，将 Bright Data 的个人资料架构规范化为 CRM 形状的联系人
* 一个**触发调用**，以异步方式触发爬取并告诉 Bright Data 将结果发送到何处

最后一跳，将每个映射的联系人 POST 到 HubSpot、Salesforce 或你自己的 CRM，是单个 fetch 调用，`route.ts` 中注释掉的块概述了这一点。

## 后续步骤

<CardGroup cols={2}>
  <Card title="异步批量请求" icon="layer-group" href="/products/scrapers/scrapers-library/async-requests">
    在单个批处理作业中爬取数百个 URL。
  </Card>

  <Card title="Amazon S3 交付" icon="bucket" href="/products/scrapers/scrapers-library/data-delivery">
    当有效负载超过 Vercel 的 4.5 MB 正文限制时，用 S3 存储桶交换 webhook。
  </Card>

  <Card title="Webhook 参考" icon="webhook" href="/products/scrapers/scrapers-library/data-delivery">
    完整的参数列表、身份验证标头和 IP 白名单。
  </Card>

  <Card title="HubSpot Contacts API" icon="hubspot" href="https://developers.hubspot.com/docs/api/crm/contacts">
    处理程序中注释 POST 的直接替换。
  </Card>
</CardGroup>
