返回博客
指南
Suciu DanLast updated on May 13, 20262 min read

如何在 2026 年抓取 LinkedIn:Python 指南

如何在 2026 年抓取 LinkedIn:Python 指南
简而言之:抓取 LinkedIn 意味着要绕过严密的身份验证壁垒、行为追踪以及 TLS 指纹识别。本指南提供了一个按页面类型分类的决策树,适用于职位、个人资料和公司的实用 Python 实现方案(包括隐藏 API、JSON-LD 以及必要时的 Selenium),以及一份针对 2026 年的综合防封检查清单。

如果你曾尝试过如何抓取 LinkedIn 数据,你很可能遇到了我们其他人同样面临的困境:仅浏览几页后就会弹出的强制登录提示,随后是静默的 999 响应,最终完全无法获取任何有用的信息。 抓取 LinkedIn 是指不登录个人账户,直接使用 HTTP 客户端、无头浏览器或隐藏 API 提取公开数据(个人资料、公司信息、职位列表及搜索结果)的操作。虽然技术难度高于抓取普通电商网站,但绝非难事。

本指南是一份面向开发者、数据工程师和增长运营团队的“代码优先”实操指南,旨在帮助您获取 LinkedIn 公开数据,同时避免烧号或盲目轮换代理。 我们将首先探讨实际可获取的数据范围,剖析 LinkedIn 如何检测爬虫,并通过决策树详细讲解三种 Python 方法(隐藏职位 API、JSON-LD 解析以及无头浏览器备用方案),以便您针对不同页面类型选择成本最低且可靠的路径。反封锁层和法律背景将在最后介绍,因为无论您选择哪种方法,这些内容都适用。

您实际可获取的 LinkedIn 数据

在探讨如何抓取 LinkedIn 数据之前,我们需要明确在认证墙之外实际可获取的内容。无需登录即可访问的页面类型有四种:公开个人资料页、公开公司页面、单个职位发布页面以及 /jobs/search 结果页面。其余内容(Sales Navigator、人员搜索索引、消息图谱、公司页面上的完整员工列表)均受身份验证保护,且涉及本指南不会触及的服务条款限制。

即便在这些公开数据中,依然蕴含着真正的价值。只要您接受数据深度的限制,并可能需要结合多方来源来填补空白,您就能获取大多数团队在招聘情报、销售开发和劳动力市场研究中所需的核心字段。

按页面类型划分的 LinkedIn 公开字段

下表列出了每种公开页面类型可提取的字段及其适用场景。许多“我们想抓取 LinkedIn 数据”的请求,一旦相关方看到无需登录即可获取的内容,便会不攻自破。

页面类型

公开字段(典型)

适用场景

个人资料 (/in/...)

姓名、职位、个人简介、所在地、个人简介摘要、个人主页链接、雇主

销售开发、招聘筛选

公司(/company/...)

名称、行业、总部、关注者、网站、职位空缺数量

客户研究、理想客户画像(ICP)构建

职位发布(/jobs/view/...)

职位名称、公司、工作地点、发布日期、职位描述、职级

劳动力市场分析、职位聚合

职位搜索(/jobs/search?...)

职位列表及分页元数据

大规模批量职位收集

如果某个字段不在该表中,则可推断是受权限限制。另有一份独立的职位数据概览,可作为合理的补充阅读。

LinkedIn如何检测并阻止爬虫

任何学习如何抓取 LinkedIn 数据的人都会很快发现,其防御机制是多层叠加的,而非从菜单中任选其一。这三层防御机制并行运行,并共同生成一个内部信号:即针对每位访问者的欺诈评分,该评分决定您的请求是获得批准、在登录提示后被软封锁,还是被完全拒绝。

第一层是身份验证壁垒。匿名访问者通常在浏览三到五个个人资料后就会被强制登录,这意味着任何使用同一身份请求数十个个人资料的爬虫,在首次运行时就会被终止。第二层是行为追踪。LinkedIn会监控请求时间、导航路径、鼠标活动以及引荐来源模式。 人类用户每分钟不会加载 100 个个人资料;而未受限的爬虫却会,仅凭这一信号就足以标记该会话。第三层是请求指纹识别。LinkedIn 会检查 IP 质量(住宅 IP 与数据中心 IP)、TLS 握手中的 JA3 哈希值、请求头和 Cookie,以及设备属性。若从 AWS IP 地址发送默认 python-requests/2.x 用户代理,会同时在这三项检测中表现不佳。

请将这些层视为累加而非替代关系。仅清理其中一层而忽略其余层,通常无法显著降低欺诈评分。在扩大规模前,建议收藏这篇关于避免被 LinkedIn 屏蔽的入门指南。

如何选择 LinkedIn 抓取方式:方法决策树

在决定如何抓取 LinkedIn 数据时,应优先选择能返回所需数据且资源消耗最小的工具。LinkedIn 采用单页应用架构,其数据流经三种机制,每种机制都对应着最理想的抓取方法。

  1. 服务器渲染的 HTML。某些页面在初始 HTML 响应中返回的数据已足够使用 Requests 配合 BeautifulSoup 进行解析。虽然在当今的 LinkedIn 上较为罕见,但仍适用于少数公司子页面和实体页面。
  2. 通过 <script> 标签中加载的 JSON。公开个人资料和公司页面会嵌入一个 <script type="application/ld+json"> 块,该块映射了可见页面所呈现的字段。解析此结构比通过 DOM 追踪 CSS 选择器更快、更经济且稳定性更高。
  3. XHR / 隐藏 API。无限滚动功能(职位信息流、公司职位列表、搜索)会调用内部端点,且查询参数具有可预测性。直接重放这些请求可完全绕过渲染过程。

经验法则:个人资料和公司页面优先尝试 JSON-LD,职位和搜索则重放隐藏 API,仅当两者均失败时才使用无头浏览器。大多数试图大规模抓取 LinkedIn 的团队,往往在 Selenium 上投入过多,而这些任务其实只需三十行 Requests 脚本即可完成。

方法 1:如何通过隐藏的 Jobs-Guest API 抓取 LinkedIn 职位

jobs-search 端点是 LinkedIn 上最容易抓取的接口:它被有意暴露给未经身份验证的访问者,且仅通过一个 start 查询参数进行分页。撰写本文时,路径为 /jobs-guest/jobs/api/seeMoreJobPostings/search,响应返回的是 HTML 职位卡片而非 JSON。由于 LinkedIn 会轮换内部接口,请在正式运行前通过开发者工具重新确认路径。

使用 BeautifulSoup 解析的简易 Python 示例如下:

import requests
from bs4 import BeautifulSoup

BASE = "https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search"
HEADERS = {
    "User-Agent": "Mozilla/5.0",
    "Accept-Language": "en-US,en;q=0.9",
}

def fetch_page(keywords, location, start=0):
    params = {"keywords": keywords, "location": location, "start": start}
    r = requests.get(BASE, params=params, headers=HEADERS, timeout=20)
    r.raise_for_status()
    return r.text

def parse_cards(html):
    soup = BeautifulSoup(html, "html.parser")
    for card in soup.select("li"):
        title = card.select_one(".base-search-card__title")
        company = card.select_one(".base-search-card__subtitle")
        loc = card.select_one(".job-search-card__location")
        link = card.select_one("a.base-card__full-link")
        if title and link:
            yield {
                "title": title.get_text(strip=True),
                "company": company.get_text(strip=True) if company else None,
                "location": loc.get_text(strip=True) if loc else None,
                "url": link["href"].split("?")[0],
            }

jobs, start = [], 0
while True:
    html = fetch_page("python developer", "Berlin", start)
    batch = list(parse_cards(html))
    if not batch:
        break
    jobs.extend(batch)
    start += 25

每页显示二十五条职位卡片。停止条件是结果集为空,而非固定的页数,因为 LinkedIn 会根据地理位置和发布时间对结果进行筛选。将 jobs 数据流输入 Python 的 csv 模块或 Pandas 数据框,即可在不使用浏览器的情况下获取 LinkedIn 职位信息流。若需复习 BeautifulSoup 选择器模式,可参考相关教程。

方法 2:如何通过 JSON-LD 抓取 LinkedIn 个人资料和公司信息

对于个人资料和公司页面,获取更多信息的技巧是完全跳过 CSS 选择器,直接解析 <script type="application/ld+json"> LinkedIn在服务器端渲染时注入的块。JSON-LD结构化、稳定,且变更频率远低于可见的DOM。要在任何公开的LinkedIn URL上找到它,请打开开发者工具并在 //script[@type='application/ld+json']

import json
import requests
from bs4 import BeautifulSoup

HEADERS = {
    "User-Agent": "Mozilla/5.0",
    "Accept-Language": "en-US,en;q=0.9",
}

def scrape_ld(url):
    r = requests.get(url, headers=HEADERS, timeout=20)
    r.raise_for_status()
    soup = BeautifulSoup(r.text, "html.parser")
    blob = soup.find("script", {"type": "application/ld+json"})
    if not blob:
        return None
    return json.loads(blob.string)

# Public profile
profile = scrape_ld("https://www.linkedin.com/in/some-public-handle/")
# Public company
company = scrape_ld("https://www.linkedin.com/company/openai/")

对于公开个人资料,通常会包含 name, jobTitle, worksFor, address,有时还包含 alumniOf。对于公司页面,通常包含 name, description, url, numberOfEmployees以及一个 address 块。LinkedIn 隐藏在登录后的任何内容(完整的员工列表、共同联系人、联系信息)都不会出现在 JSON-LD 中;这不是解析错误,而是授权壁垒。

仅对 JSON-LD 未公开的字段(例如公司页面上的“相似页面”轮播图)回退到 HTML 解析,并将这些选择器视为管道中最脆弱的部分。这也是维护工作最耗时的地方,因为 LinkedIn 通常每两到四周就会重构其前端标记。

方法 3:使用无头浏览器处理搜索和延迟加载的区域

仅当前两种方法无法满足需求时,才考虑使用 Selenium 或 Playwright。常见场景包括人员搜索结果、延迟加载的“该公司职位”标签页,以及任何在滚动事件后才显示关键数据的页面。如果您此前未曾构建过此类系统,建议先阅读无头浏览器入门指南;若需要,Selenium 配合 Python 的教程会详细指导驱动程序的配置。

最简工作流如下:启动 Chromium 驱动程序,使用真实的用户代理进行导航,等待网络连接稳定,滚动直到相关内容加载完成,然后使用 Selenium 定位器获取 DOM,或者将 driver.page_source 传递给 BeautifulSoup。切勿在 Selenium 环境中登录真实的 LinkedIn 账户。这种操作违反 LinkedIn 的服务条款,也是导致账户被永久封禁的最快途径。

无头浏览器本身并非反机器人解决方案。原生 Puppeteer 和 Playwright 在 JA3 和 navigator 对象级别被识别,因此你仍需采用下一节所述的代理和速率控制措施。如果某项任务无需浏览器即可完成,请尽量避免使用浏览器。

防封检查清单:代理、头部信息、JA3 和速率控制

当团队在研究如何抓取 LinkedIn 时,从一次性脚本转向定期爬取,失败的原因几乎总是反机器人机制,而非解析问题。请按顺序执行以下措施。

  1. 使用住宅代理,而非数据中心代理。LinkedIn 维护着一份针对数据中心 ASN 的严格黑名单。住宅代理池会轮换真实的消费者 ISP IP,因此更难被标记。如果你之前没有配置过 IP 轮换,那么关于如何在 Python Requests 中使用代理的指南是最佳的入门起点。
  2. 注意你的 JA3 指纹。纯文本 requests 的 TLS 指纹与任何真实浏览器均不匹配。封装 curl_cffi 或重放真实浏览器 JA3 哈希的工具能通过此检测;而 raw requests 则无法通过。
  3. 发送完整的头部集。至少应包含:当前 User-Agent, Accept, Accept-Language, Accept-Encoding,以及一个合理的 Referer。缺失 Accept-Language 本身就是强有力的爬虫特征。
  4. 控制节奏。限制并发数,延迟抖动控制在1到5秒之间,切勿突发访问。
  5. 轮换身份信息,而不仅仅是 IP 地址。每次 IP 轮换都应配合全新的用户代理和 Cookie 集,以防止 LinkedIn 将会话拼接起来。

如果遵循以上建议后仍被软封禁,问题在于流量规模,而非配置。请放慢速度。

抓取 LinkedIn 是否合法?

美国最具代表性的案例是 hiQ Labs 诉 LinkedIn 一案,法院在该案中概括性地裁定,抓取公开可访问的 LinkedIn 数据并不违反《计算机欺诈与滥用法案》。该诉讼从 2017 年左右持续至 2022 年,并在第九巡回上诉法院发布意见书后结束;关于裁决的当前状态和确切范围,EFF 网站上关于 hiQ 诉 LinkedIn 案的页面是一个清晰且适合初学者的参考资料。 该裁决有两点需注意:它并未推翻领英的《服务条款》(该条款仍禁止在登录状态下进行自动化访问),且其效力不适用于美国司法管辖范围之外。若您进行的是商业规模的数据抓取,请将此裁决仅作为背景参考,并在正式上线前咨询法律顾问。关于网页抓取是否合法的一般性入门指南也值得一读。

关键要点

  • 根据页面类型选择方法,而非依据个人习惯。JSON-LD 适用于个人资料和公司页面,隐藏的职位 API 适用于职位列表和搜索,而无头浏览器应作为备选方案,而非默认选择。
  • 三层防御机制,一个欺诈评分。身份验证墙、行为追踪以及 TLS/标头指纹识别都会影响同一个内部评分;仅清理其中一项通常无法改变结果。
  • 住宅代理配合支持JA3的HTTP客户端是基础配置。仅使用数据中心IP无法在领英构建出可运行的爬取管道。
  • 切勿通过自动化登录。此举违反服务条款,无论你的选择器设计得多么谨慎,都将导致账户被永久封禁。
  • 预留故障处理方案。LinkedIn通常每隔几周就会重构前端;请设计可在单个文件中替换的筛选器和JSON解析器。

常见问题

不登录账户能否抓取 LinkedIn 数据?

可以,但仅限于公开内容。公开个人主页、公司主页、单个职位发布以及 /jobs/search 端点在无需认证的情况下均可访问。但 Sales Navigator、人员搜索索引、共同联系人数据以及公司页面上的完整员工列表则不可访问。匿名爬虫在浏览约三到五个个人资料后也会触发登录提示,因此请从项目启动之初就规划好 IP 和身份轮换策略。

我应该使用 LinkedIn 的官方 API 而不是进行抓取吗?

对于常规数据采集,通常不建议。LinkedIn官方API的适用范围非常有限:它专为合作伙伴集成设计,例如职位申请、内容分享或营销自动化,无法返回大多数爬虫项目所需的公开个人资料或公司数据。大多数评估过官方API的团队最终都会通过爬取公开网站来补充API无法覆盖的内容。

LinkedIn 爬取最适合使用哪种代理?住宅代理还是数据中心代理?

建议使用住宅代理,并配合轮换机制。LinkedIn对数据中心ASN(如AWS、GCP、OVH等)设有严格的封禁列表,因此数据中心IP极易被限速或收到999响应。住宅代理池通过真实的消费者ISP IP进行路由,其流量特征与普通用户无异。对于小规模的一次性抓取,移动代理虽也可行,但对于大多数任务而言,其性能过剩且成本更高。

如何判断我的 LinkedIn 爬虫即将被封禁?

请留意三个早期预警信号。首先,响应时间骤增(LinkedIn通常会在封禁前延迟响应)。其次,返回登录弹窗而非内容的页面数量增加。第三,出现HTTP 999响应,这是LinkedIn特有的“您已被标记”代码。如果这三项指标中任何一项在1小时内呈上升趋势,请暂停爬取并轮换身份,以免情况恶化。

LinkedIn 多久会更改页面结构并导致爬虫失效?

频繁。前端 HTML 和 CSS 选择器通常每两到四周调整一次,内部 Voyager API 接口大约每四到八周轮换一次,而 JSON-LD 结构往往能保持数月稳定。尽可能将爬虫基于 JSON-LD 或隐藏 API 构建,将易变的 CSS 选择器隔离到单独的模块中,并预留每月进行一次小规模维护的时间。

总结

要搞定 LinkedIn 的大规模抓取,关键不在于花哨的技巧,而在于严谨的纪律。针对每种页面类型选择最轻量级的方法,尊重身份验证壁垒,并将反机器人层视为首要关注点而非事后补救。JSON-LD 将承担您大部分个人资料和公司信息的工作,而 jobs-guest 接口将承担您大部分招聘市场相关的工作。 将 Selenium 保留给真正动态的界面,切勿在登录状态下运行,并将工程时间投入到代理、速率控制和 JA3 规范中,而非编写更花哨的 Selenium 脚本。

维护是工作的另一半。LinkedIn以数周为周期重构其前端,因此请设计能“高调报错”的解析器,记录结构变更,并隔离选择器,以便修复时只需修改一个文件而非重写代码。

若您希望完全跳过代理、指纹识别和验证码层,直接专注于数据本身,WebScrapingAPI 的 Scraper API 可在单一接口后处理请求端(IP 轮换、JA3、头部信息、重试),并返回原始 HTML 代码——您可使用上述已编写的 Requests 配合 BeautifulSoup 的代码进行解析。数据抓取逻辑由您掌控;障碍清除则交给我们。

关于作者
Suciu Dan, 联合创始人 @ WebScrapingAPI
Suciu Dan联合创始人

Suciu Dan 是 WebScrapingAPI 的联合创始人,他撰写了关于 Python 网页抓取、Ruby 网页抓取以及代理基础设施的实用指南,这些指南专为开发者而设计。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网络数据。