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

# Business Search 查询示例

> Business Search 查询示例，针对单次请求无法回答的问题，例如通过两次连续搜索查找某城市已获融资公司的 CEO。

本页介绍如何用 Business Search 回答潜在客户挖掘问题，包括需要依次运行公司搜索和人物搜索的问题。

## 如何按融资和地点查找公司的 CEO

要查找总部位于旧金山、最近一轮融资为 1 USD 至 200 万 USD 的科技公司的 CEO，请先运行公司搜索找到这些公司，再运行人物搜索找到这些公司的 CEO。

单次 Business Search 请求无法回答这个问题。人物搜索只能按[人物可搜索字段](/cn/products/business-search/people-search#可搜索字段)筛选，例如 `current_title` 和 `current_company_name`。融资和总部属于[公司可搜索字段](/cn/products/business-search/company-search#可搜索字段)。人物记录可以在视图中返回 `current_company_funding_raised`，但人物搜索无法按该字段筛选。

### 前提条件

* 一个具有 Business Search 访问权限的 Bright Data API 密钥，存储在 `BRIGHTDATA_API_KEY` 环境变量中。参见 [Business Search 快速入门](/cn/products/business-search/quickstart)
* Python 标签页需要安装了 `requests` 包的 Python 3；Node.js 标签页需要 Node.js 18 或更高版本

### 第 1 步：查找公司

在 [Instant 模式](/cn/products/business-search/introduction#搜索模式)下，把问题中与公司相关的部分作为一句话发送。视图请求 `company_id`（第 3 步用它把人物匹配到公司），以及 `headquarters_city` 和 `funding_raised`，便于逐一核对每家公司是否符合问题：

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST "https://api.brightdata.com/search/company" \
    --header "Authorization: Bearer $BRIGHTDATA_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "mode": "instant",
      "query": "Technology companies headquartered in San Francisco whose latest funding round was between $1 and $2 million",
      "limit": 100,
      "view": { "fields": ["company_id", "name", "headquarters_city", "funding_raised"] }
    }'
  ```

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

  API = "https://api.brightdata.com/search"
  HEADERS = {
      "Authorization": f"Bearer {os.environ['BRIGHTDATA_API_KEY']}",
      "Content-Type": "application/json",
  }

  response = requests.post(
      f"{API}/company",
      headers=HEADERS,
      json={
          "mode": "instant",
          "query": "Technology companies headquartered in San Francisco whose latest funding round was between $1 and $2 million",
          "limit": 100,
          "view": {"fields": ["company_id", "name", "headquarters_city", "funding_raised"]},
      },
  )
  response.raise_for_status()
  companies = {
      str(doc["data"]["company_id"]): doc["data"]["name"]
      for doc in response.json()["documents"]
      if "company_id" in doc["data"] and "name" in doc["data"]
  }
  print(f"{len(companies)} companies found")
  ```

  ```javascript Node.js theme={null}
  const API = "https://api.brightdata.com/search";
  const HEADERS = {
    Authorization: `Bearer ${process.env.BRIGHTDATA_API_KEY}`,
    "Content-Type": "application/json",
  };

  const companyResponse = await fetch(`${API}/company`, {
    method: "POST",
    headers: HEADERS,
    body: JSON.stringify({
      mode: "instant",
      query: "Technology companies headquartered in San Francisco whose latest funding round was between $1 and $2 million",
      limit: 100,
      view: { fields: ["company_id", "name", "headquarters_city", "funding_raised"] },
    }),
  });
  if (!companyResponse.ok) throw new Error(await companyResponse.text());

  const companies = new Map();
  for (const doc of (await companyResponse.json()).documents) {
    if (doc.data.company_id != null && doc.data.name) {
      companies.set(String(doc.data.company_id), doc.data.name);
    }
  }
  console.log(`${companies.size} companies found`);
  ```
</CodeGroup>

Instant 最多返回前 100 条匹配结果。如需一份按每家公司与该句子的契合程度排序的较短列表，请以 `"mode": "smart"` 和 `"limit": 10` 发送同样的请求体。Smart 每次搜索的费用更高。参见 [Business Search 价格](/cn/products/business-search/pricing)。

### 第 2 步：搜索这些公司的 CEO

在 [Ludicrous 模式](/cn/products/business-search/introduction#搜索模式)下发送人物搜索，因为此时的输入是第 1 步得到的公司名称列表，而不是一句话。每次请求将 CEO 职位条件与最多 10 个公司名称组合，作为 `current_company_name` 上的 `or` 条件：

<CodeGroup>
  ```bash cURL theme={null}
  curl --request POST "https://api.brightdata.com/search/people" \
    --header "Authorization: Bearer $BRIGHTDATA_API_KEY" \
    --header "Content-Type: application/json" \
    --data '{
      "mode": "ludicrous",
      "query": {
        "and": [
          {
            "or": [
              { "text": { "current_title": "CEO" } },
              { "text": { "current_title": { "value": "chief executive officer", "mode": "all" } } }
            ]
          },
          {
            "or": [
              { "text": { "current_company_name": { "value": "COMPANY_NAME_1", "mode": "all" } } },
              { "text": { "current_company_name": { "value": "COMPANY_NAME_2", "mode": "all" } } }
            ]
          }
        ]
      },
      "limit": 100,
      "view": { "fields": ["current_title", "current_company_name", "current_company_id"] }
    }'
  ```

  ```python Python theme={null}
  ceo_title = {
      "or": [
          {"text": {"current_title": "CEO"}},
          {"text": {"current_title": {"value": "chief executive officer", "mode": "all"}}},
      ]
  }

  names = list(companies.values())
  people = {}
  for start in range(0, len(names), 10):
      batch = names[start:start + 10]
      response = requests.post(
          f"{API}/people",
          headers=HEADERS,
          json={
              "mode": "ludicrous",
              "query": {
                  "and": [
                      ceo_title,
                      {
                          "or": [
                              {"text": {"current_company_name": {"value": name, "mode": "all"}}}
                              for name in batch
                          ]
                      },
                  ]
              },
              "limit": 100,
              "view": {"fields": ["current_title", "current_company_name", "current_company_id"]},
          },
      )
      response.raise_for_status()
      for doc in response.json()["documents"]:
          people[doc["bright_id"]] = doc["data"]

  print(f"{len(people)} candidate profiles found")
  ```

  ```javascript Node.js theme={null}
  const ceoTitle = {
    or: [
      { text: { current_title: "CEO" } },
      { text: { current_title: { value: "chief executive officer", mode: "all" } } },
    ],
  };

  const names = [...companies.values()];
  const people = new Map();
  for (let start = 0; start < names.length; start += 10) {
    const batch = names.slice(start, start + 10);
    const peopleResponse = await fetch(`${API}/people`, {
      method: "POST",
      headers: HEADERS,
      body: JSON.stringify({
        mode: "ludicrous",
        query: {
          and: [
            ceoTitle,
            { or: batch.map((name) => ({ text: { current_company_name: { value: name, mode: "all" } } })) },
          ],
        },
        limit: 100,
        view: { fields: ["current_title", "current_company_name", "current_company_id"] },
      }),
    });
    if (!peopleResponse.ok) throw new Error(await peopleResponse.text());
    for (const doc of (await peopleResponse.json()).documents) {
      people.set(doc.bright_id, doc.data);
    }
  }
  console.log(`${people.size} candidate profiles found`);
  ```
</CodeGroup>

Python 和 Node.js 代码每批 10 个名称发送一次请求，并以 `bright_id` 为键保存结果，因此被两个批次同时返回的档案只保留一次。在 cURL 标签页中，把 `COMPANY_NAME_1` 和 `COMPANY_NAME_2` 替换为第 1 步得到的公司名称，每个名称添加一个条件。每次请求都是一次单独计费的搜索，因此 100 家公司共需 11 次搜索。

### 第 3 步：保留公司匹配的档案

只保留 `current_company_id` 属于第 1 步 `company_id` 值之一的档案。使用 cURL 时，请对比第 1 步和第 2 步响应中的这两个值：

<CodeGroup>
  ```python Python theme={null}
  ceos = [p for p in people.values() if str(p.get("current_company_id")) in companies]

  for person in ceos:
      print(f"{person['current_title']} at {companies[str(person['current_company_id'])]}")
  ```

  ```javascript Node.js theme={null}
  const ceos = [...people.values()].filter((p) => companies.has(String(p.current_company_id)));

  for (const person of ceos) {
    console.log(`${person.current_title} at ${companies.get(String(person.current_company_id))}`);
  }
  ```
</CodeGroup>

仅靠第 2 步的搜索还不够。`current_company_name` 是文本字段，条件会匹配公司名称包含这些词的所有档案：`Acme` 也会匹配 `Acme Robotics`。按公司 ID 匹配会剔除这些档案，也会剔除没有 `current_company_id` 的档案。
