# 如何抓取Indeed职位发布：结构、模块和SERP路线

Indeed是网络上最大的招聘网站，也是实时劳动力市场信号的来源。它还使用Cloudflare，类名每周轮换。以下是如何持久地提取数据——以及何时完全跳过该网站。

Indeed每月约有5.42亿次访问，使其列表成为劳动力市场最清晰的实时信号之一——按角色的招聘需求、薪资范围、哪些公司在招聘。它也是一个受Cloudflare保护的React网站，其可见的CSS类名经常轮换，足以在几周内破坏一个简单的抓取器。本指南展示了如何持久地抓取Indeed职位发布，如何分页和去重，Cloudflare现实，以及让你完全跳过争斗的职位SERP垂直。

## 阅读搜索页面，锚定在稳定的属性上

Indeed数据的单位是搜索结果页面：查询加上位置为你提供一个职位卡片页面。陷阱在于选择Indeed重新生成的哈希类名（如`eu4oa1w0`）。相反，锚定在变化频率较低的`data-testid`属性上：

```python
import requests
from bs4 import BeautifulSoup

headers = {
    "User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 "
                  "(KHTML, like Gecko) Chrome/146.0.0.0 Safari/537.36",
    "Accept-Language": "en-US,en;q=0.9",
}
proxies = {"http": "http://USER:PASS@residentialpremium.quantumproxies.io:8080",
           "https": "http://USER:PASS@residentialpremium.quantumproxies.io:8080"}

url = "https://www.indeed.com/jobs?q=python&l=New+York%2C+NY"
html = requests.get(url, headers=headers, proxies=proxies, timeout=30).text
soup = BeautifulSoup(html, "html.parser")

jobs = []
for card in soup.select("div.job_seen_beacon"):
    title = card.find("a", class_="jcs-JobTitle")
    company = card.find("span", attrs={"data-testid": "company-name"})
    location = card.find("div", attrs={"data-testid": "text-location"})
    jobs.append({
        "title": title.get_text(strip=True) if title else None,
        "company": company.get_text(strip=True) if company else None,
        "location": location.get_text(strip=True) if location else None,
        "jk": title["href"].split("jk=")[-1][:16] if title else None,
    })
print(len(jobs), "jobs on page 1")
```

每个卡片都有一个职位键（`jk`）——一个你用来跨页面和运行去重的稳定ID。存储在`jk`上，而不是URL，因为同一发布会以不同的跟踪参数出现。

## 分页和国家网站

Indeed页面使用一个`start`参数，每次增加10。并且它不是一个网站——每个国家是一个子域：美国是`www.indeed.com`，英国是`uk.indeed.com`，等等。将你的代理出口与查询的国家匹配，以确保请求在地理上连贯：

```python
def crawl(query, location, country="www", pages=5):
    base = f"https://{country}.indeed.com/jobs"
    for start in range(0, pages * 10, 10):
        params = {"q": query, "l": location, "start": start}
        html = requests.get(base, params=params, headers=headers,
                            proxies=proxies, timeout=30).text
        # parse as above, yield rows
        yield html

# freshness filter: fromage accepts only 1, 3, 7 or 14 days
# .../jobs?q=python&l=NYC&fromage=7
```

一个值得了解的特点：Indeed的“发布于”过滤器（`fromage`）只接受1、3、7或14天——其他值会被忽略，因此围绕这些桶构建你的新鲜度逻辑。

![Indeed 抓取流水线：通过住宅出口请求查询 URL，使 Cloudflare 正常返回页面，按 data-testid 解析职位卡片，以 10 为增量用 start 翻页，并按职位键去重；卡片列出了关键参数：start、取值为 1、3、7 或 14 天的 fromage、国家子域名、jk。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335181/blog/generated/qp-b9-046-diag1.png)
*锚定在data-testid和职位键上；按10的增量分页并去重，以捕获完整的结果集。*

## Cloudflare现实

Indeed位于Cloudflare之后，因此使用数据中心IP进行简单请求通常会得到挑战而不是结果。解决方法是常见的反机器人堆栈：一致的浏览器User-Agent和头设置，以及——最大的杠杆——一个未被预先评分为自动化的住宅出口。[住宅代理](https://quantumproxies.io/residential-proxies)呈现为真实用户的连接，这就是Cloudflare继续提供页面的原因。当出现挑战时，匹配浏览器指纹与IP同样重要；我们关于[2026年绕过Cloudflare挑战](https://quantumproxies.io/blog/how-to-bypass-cloudflare-challenges-in-2026-what-actually-matters-now)的指南涵盖了界限所在。

## 捷径：职位SERP垂直

如果你真正想要的是劳动力市场数据——而不是Indeed的HTML——那么有一个更简洁的路径。Google的职位垂直整合了来自Indeed和许多其他网站的发布，[SERP API](https://quantumproxies.io/serp-api)以解析的JSON返回该职位垂直：标题、公司、位置、发布日期和来源，无需维护CSS选择器，也无需与Cloudflare斗争。你以一些字段级别的控制换取一个跨多个网站的稳定结构化提要，对于聚合招聘分析来说，这通常是更好的选择。这也是基于SERP提要构建[职位板聚合器](https://quantumproxies.io/blog/job-board-aggregator-scraping)而不是每个网站一个抓取器的原因。

[将职位垂直拉为干净的JSON](https://quantumproxies.io/serp-api)

## 数据的用途

除了职位搜索之外，这些数据还推动了实际分析：按角色和城市的薪资基准，特定技能随时间的需求跟踪，竞争对手招聘信号（竞争对手组建新团队是战略信号），以及丰富——将公司的开放职位与公司特征结合用于外部。将其与[Glassdoor薪资数据](https://quantumproxies.io/blog/scrape-glassdoor-salary-reviews)结合，你会得到比单一来源更完整的薪酬图景。

![获取同一职位数据的两条路线：直接抓取 Indeed 可以完全控制字段，但需要维护选择器并通过 Cloudflare；而职位 SERP 垂直接口返回覆盖众多招聘网站的干净 JSON；卡片列出了 JSON 字段：职位名称、公司、地点、发布日期和来源。](https://res.cloudinary.com/dmqliab0t/image/upload/f_auto,q_auto,w_1200/v1785335181/blog/generated/qp-b9-046-diag2.png)
*抓取Indeed提供完整的字段控制；职位SERP垂直提供跨多个网站的结构化JSON，无需选择器维护。*

## 常见问题解答

### 可以合法地抓取Indeed职位发布吗？

职位发布是公共数据，收集公开可见的列表在广泛上是可辩护的，但Indeed的条款限制自动访问，你应避免个人数据并尊重速率限制。许多团队通过使用聚合的职位SERP垂直而不是直接抓取Indeed来规避条款问题。这是一般信息，而非法律建议——在进行大型项目之前请查看当前条款。

### 为什么我的Indeed抓取器总是崩溃？

有两个原因。首先，Indeed轮换其哈希CSS类名，因此固定在它们上的选择器在几周内失效——相反，锚定在`data-testid`属性和职位键上。其次，一旦你的IP被标记，Cloudflare就会开始挑战；住宅出口和一致的浏览器指纹保持真实页面加载。修复这两点，抓取器就会稳定。

### 如何从多个国家抓取职位？

Indeed为每个国家提供自己的子域（`www.indeed.com`，`uk.indeed.com`，`de.indeed.com`，等等）。查询正确的子域并通过该国家的代理出口路由，以确保请求在地理上连贯——否则你可能会得到不匹配或重定向的结果。如果你不想管理子域，职位SERP垂直也接受国家参数。

### Google职位SERP比抓取Indeed更好吗？

对于聚合劳动力市场分析，通常是的。职位垂直将来自Indeed和许多其他网站的发布作为结构化JSON返回，无需处理旋转选择器和Cloudflare挑战。你会失去一些Indeed特定的字段，但你会获得一个稳定的多源提要，并且维护工作大大减少。只有当你需要Indeed自己页面上的字段时，才直接抓取Indeed。

Indeed奖励持久的方法：锚定在稳定的属性上，通过职位键去重，按十分页，并使用住宅IP敲门以便Cloudflare为你服务。当你只需要劳动力市场信号而不是Indeed的确切HTML时，职位SERP垂直以JSON形式提供。选择与你实际需要的字段控制相匹配的路径。

[获取能通过Cloudflare的住宅IP](https://quantumproxies.io/residential-proxies)
