PAYATHON 2026

如何使用 Python 从不同公司官网提取领导团队姓名和职务?

数据小许

可以用 Python 完成。需要先确认公司官网并找到相关页面,再提取姓名和职务,最后验证结果。官网布局和栏目名称各不相同,单一 CSS selector 难以可靠覆盖所有网站。

采集前还要明确范围:Leadership、Executive Team 和 Board Members 可能分别对应管理团队、高管团队和董事会。董事不一定参与日常管理,不能把这些页面上的人员全部归为同一类。

1. 先确认官网,再寻找团队页面

如果运行时只有公司名称,需要先通过搜索服务或可信的公司资料找到候选官网,再核对公司全称、地区和业务等信息。同名公司可能对应不同域名,不建议直接把搜索结果的第一项当成官网。

确认域名后,可以从首页导航、页脚、About 页面以及网站提供的 sitemap 中寻找相关链接。匹配词可以包括:

  • Leadership、Management、Executive Team。
  • Board、Directors、Governance。
  • “领导团队”“管理团队”“董事会”。

这些词只能用来发现候选页面,还要结合页面标题和正文判断它介绍的是哪类人员。

2. 优先读取结构化数据,再处理页面布局

如果目标页面的 JSON-LD 中包含 Person、name 和 jobTitle,可以先提取这些字段。没有这类数据时,再分析人员卡片、列表或表格,将同一区域中的姓名与职务配对。

不要分别收集整个页面的所有姓名和职务,再按顺序拼接。隐藏元素、重复导航或缺失字段都可能导致错配。

下面的示例会发现当前页面中的相关链接,并提取 JSON-LD 中带有姓名和职务的 Person 候选记录。它只处理服务器返回的 HTML,不执行 JavaScript。

安装依赖:

pip install requests beautifulsoup4
import json
from urllib.parse import urljoin, urlsplit

import requests
from bs4 import BeautifulSoup


TERMS = (
    "leadership", "management", "executive", "board",
    "directors", "governance", "team", "about",
    "领导", "管理团队", "董事", "关于",
)


def walk_json(value):
    if isinstance(value, dict):
        yield value
        for child in value.values():
            yield from walk_json(child)
    elif isinstance(value, list):
        for child in value:
            yield from walk_json(child)


def inspect_page(url):
    response = requests.get(url, timeout=20)
    response.raise_for_status()
    page_url = response.url
    soup = BeautifulSoup(response.content, "html.parser")

    candidate_pages = set()
    for link in soup.select("a[href]"):
        target = urljoin(page_url, link["href"])
        parsed = urlsplit(target)
        label = f"{link.get_text(' ', strip=True)} {target}".casefold()
        if (
            parsed.scheme in {"http", "https"}
            and parsed.hostname == urlsplit(page_url).hostname
            and any(term in label for term in TERMS)
        ):
            candidate_pages.add(parsed._replace(fragment="").geturl())

    people = {}
    for script in soup.find_all("script", type="application/ld+json"):
        try:
            data = json.loads(script.get_text())
        except (ValueError, TypeError):
            continue

        for item in walk_json(data):
            types = item.get("@type", [])
            if isinstance(types, str):
                types = [types]
            if not isinstance(types, list) or "Person" not in types:
                continue

            name = item.get("name")
            title = item.get("jobTitle")
            if isinstance(name, str) and isinstance(title, str):
                name, title = name.strip(), title.strip()
                if name and title:
                    people[(name, title)] = {
                        "name": name,
                        "designation": title,
                        "source_url": page_url,
                    }

    return {
        "candidate_pages": sorted(candidate_pages),
        "person_candidates": list(people.values()),
    }


if __name__ == "__main__":
    # 替换为已经确认的公司官网地址。
    result = inspect_page("https://company.example/")
    print(json.dumps(result, ensure_ascii=False, indent=2))

先检查返回的 candidate_pages,确认相关页面后,再将其地址传给 inspect_page()。示例只接受同一主机名下的链接;如果官网把投资者关系或董事会信息放在独立子域名,需要核实后将该主机加入允许范围。

person_candidates 中的记录也需要核对。JSON-LD 中的 Person 可能是文章作者或其他人员,必须结合页面内容判断其是否属于目标团队。没有返回记录,只表示这段代码没有找到符合条件的数据,不能据此认定公司没有领导团队信息。

3. 没有 JSON-LD 时,为页面结构设置提取规则

如果页面使用重复的人员卡片,可以先定位每张卡片,再在卡片内部寻找姓名、职务和个人简介链接。例如:

# 选择器仅演示提取方式,需要根据目标页面的实际 HTML 修改。
for card in soup.select(".leader-card"):
    name_node = card.select_one(".name")
    title_node = card.select_one(".job-title")
    if name_node is None or title_node is None:
        continue

    person = {
        "name": name_node.get_text(" ", strip=True),
        "designation": title_node.get_text(" ", strip=True),
    }

如果团队页面只有姓名和简介链接,可能需要进入个人页面才能找到职务。跨公司采集时,可以复用页面发现和字段验证逻辑,再为无法通用处理的网站维护单独规则。

对于任意未知官网,程序应允许返回“未找到”“需要渲染”或“需要复核”,避免为了填满字段而猜测姓名和职务。

4. 页面依赖 JavaScript 时,再考虑浏览器渲染

如果浏览器中能看到人员信息,而 HTTP 响应中没有,页面可能通过 JavaScript 加载数据。此时可以检查页面实际使用的数据请求,或使用 Playwright 获取渲染后的页面内容,再执行提取。

浏览器渲染会增加耗时和资源消耗,适合在普通 HTTP 请求无法获得内容时启用。抓取失败、访问受限和页面没有相关信息,也应分别记录状态,方便后续判断。

5. 验证结果时保留上下文

即使信息只在内存中用于验证,处理过程中也应保留来源页面和原始职务文本。至少核对以下内容:

  • 页面属于已确认的公司官网,且描述的是目标公司或目标业务实体。
  • 姓名和职务来自同一人员区域,具有明确对应关系。
  • 页面介绍的是现任成员,而不是历史公告、新闻报道或离任人员。
  • 董事会成员与管理团队成员按实际角色区分。

如果需要统一职位名称,可以另外生成标准化字段,同时保留原文。例如,CEO 与 Chief Executive Officer 可以按业务规则映射,但 Chair、Director 和 Managing Director 不宜仅凭关键词归为同一职位。

采集时应检查网站的访问规则,设置合理频率,并避免在日志中意外保存原本不打算留存的人员信息。即使采集仅用于验证,也需要检查网站的访问要求。

备注:内容仅供参考。