发送 LinkedIn 或 Indeed 搜索、职位页面或招聘页,Web Unlocker 就按访客看到的样子返回它:LinkedIn 60 个职位或 Indeed 50 个,按 1 页计费。无需登录,无需招聘网站 API。页面加载失败不收费。
1,000 次免费请求 · 仅成功时计费 · 195+ 个国家和地区 · 适配 Claude
简单介绍一下您的团队,即可获得:
一个 LinkedIn 职位搜索页包含 60 张职位卡片,带有标题、公司、地点和发布日期,Web Unlocker 按 1 页计费。Apify 和 Bright Data 上的 LinkedIn 职位采集工具则把每个职位各算作一条记录来计费,ScraperAPI 采集一个 LinkedIn 页面收取 30 个积分。
一页,60 个职位。
167 页,10,000 个职位。
需要完整描述吗?每个职位自己的页面多一次请求,所以 1,000 条描述合计 $0.98。一个 Indeed 搜索页包含 50 个职位,价格相同,公司招聘页也是如此。
来自搜索页的 10,000 个 LinkedIn 职位的费用
167 个各含 60 个职位的搜索页,按公布价格计算
准备好用在自己的搜索上了吗?获取 API 密钥和免费请求额度。
连续请求一百个职位页面,不重试:25 个城市的 LinkedIn 搜索、搜索的后续页面、带完整描述的职位页面、Indeed 搜索和职位页面,以及 Lever、Ashby、Greenhouse 和 Workday 上的公司招聘页。
没有返回的页面计费 $0。
您为页面付费,而不是为尝试次数付费。
把 LinkedIn 搜索限定在最近 24 小时,页面上的每个职位都是一天内发布的,新发布时还标有 Be an early applicant。您的脚本想多频繁就多频繁地请求这一页:每小时检查一次,每天 24 页,每月 $0.71。
职位数据集每周或每月才更新一次。
您的页面就是这一小时的。
招聘网站数据采集无需自建浏览器集群:Web Unlocker 返回页面,职位卡片就是普通 HTML,几行代码即可读取。同一个请求适用于 LinkedIn、Indeed 和公司招聘页。
填写上面的表单。密钥会在一个工作日内通过邮件送达。
LinkedIn 或 Indeed 搜索、搜索的后续页面、带描述的职位详情页,或公司的招聘页。
从页面中截取职位卡片,保留您需要的字段:标题、公司、地点、日期和链接。
pip install requestsGOLOGIN_SCRAPING_API_KEY=your_key python linkedin_jobs.pyhttps://parsing.webunlocker.gologin.com/v1/scrapeimport html
import json
import os
import re
import time
from urllib.parse import urlencode
import requests
query = "data analyst"
where = "Chicago, IL"
def scrape(url):
for attempt in range(3):
response = requests.get(
"https://parsing.webunlocker.gologin.com/v1/scrape",
params={"url": url, "geo": "us", "format": "json"},
headers={"apikey": os.environ["GOLOGIN_SCRAPING_API_KEY"]},
timeout=90,
)
page = response.json().get("data", {}).get("html", "") if response.ok else ""
if "urn:li:jobPosting:" in page:
return page
time.sleep(5)
raise RuntimeError("No jobs came back, try again later")
def text(pattern, card):
found = re.search(pattern, card, re.S)
return " ".join(html.unescape(re.sub(r"<[^>]+>", " ", found.group(1))).split()) if found else None
search = "https://www.linkedin.com/jobs/search?" + urlencode({"keywords": query, "location": where})
page = scrape(search)
jobs = []
for card in page.split("<li")[1:]:
job_id = re.search(r"urn:li:jobPosting:(\d+)", card)
if not job_id:
continue
jobs.append({
"title": text(r'base-search-card__title[^>]*>(.*?)</h3>', card),
"company": text(r'base-search-card__subtitle[^>]*>(.*?)</h4>', card),
"location": text(r'job-search-card__location[^>]*>(.*?)</span>', card),
"posted": text(r"<time[^>]*>(.*?)</time>", card),
"date": text(r'datetime="([^"]+)"', card),
"url": "https://www.linkedin.com/jobs/view/" + job_id.group(1),
})
print(json.dumps({"query": query, "where": where, "jobs_on_page": len(jobs), "jobs": jobs}, indent=2, ensure_ascii=False))GOLOGIN_SCRAPING_API_KEY=your_key node linkedin-every-page.mjshttps://parsing.webunlocker.gologin.com/v1/scrapeimport { writeFileSync } from 'node:fs';
const query = 'registered nurse';
const where = 'Texas, United States';
async function scrape(url) {
for (let attempt = 1; attempt <= 3; attempt++) {
const params = new URLSearchParams({ url, geo: 'us', format: 'json' });
const response = await fetch(`https://parsing.webunlocker.gologin.com/v1/scrape?${params}`, {
headers: { apikey: process.env.GOLOGIN_SCRAPING_API_KEY },
});
const body = response.ok ? await response.json() : null;
if (body?.success) return body.data?.html ?? '';
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error(`Nothing came back for ${url}, try again later`);
}
const text = (card, pattern) =>
(card.match(pattern)?.[1] ?? '').replace(/<[^>]+>/g, ' ').replace(/&/g, '&').replace(/'/g, "'").replace(/\s+/g, ' ').trim();
const cell = (value) => `"${value.replace(/"/g, '""')}"`;
const jobs = new Map();
let pages = 0;
for (let start = 0; start < 1000; start += 10) {
const params = new URLSearchParams({ keywords: query, location: where, start });
const page = await scrape(`https://www.linkedin.com/jobs-guest/jobs/api/seeMoreJobPostings/search?${params}`);
pages += 1;
const cards = page.split('<li').slice(1).filter((card) => card.includes('urn:li:jobPosting:'));
if (cards.length === 0) break;
for (const card of cards) {
const id = card.match(/urn:li:jobPosting:(\d+)/)[1];
jobs.set(id, [
text(card, /base-search-card__title[^>]*>([\s\S]*?)<\/h3>/),
text(card, /base-search-card__subtitle[^>]*>([\s\S]*?)<\/h4>/),
text(card, /job-search-card__location[^>]*>([\s\S]*?)<\/span>/),
card.match(/datetime="([^"]+)"/)?.[1] ?? '',
`https://www.linkedin.com/jobs/view/${id}`,
]);
}
}
const rows = [['title', 'company', 'location', 'date', 'url'], ...jobs.values()];
writeFileSync('linkedin-jobs.csv', rows.map((row) => row.map(cell).join(',')).join('\n'));
console.log(`${jobs.size} jobs from ${pages} pages saved to linkedin-jobs.csv`);
console.log(rows.slice(1, 4).map((row) => row.slice(0, 3).join(' | ')).join('\n'));GOLOGIN_SCRAPING_API_KEY=your_key node two-boards.mjshttps://parsing.webunlocker.gologin.com/v1/scrapeconst query = 'software engineer';
const city = 'Austin, TX';
async function scrape(url, marker) {
for (let attempt = 1; attempt <= 3; attempt++) {
const params = new URLSearchParams({ url, geo: 'us', format: 'json' });
const response = await fetch(`https://parsing.webunlocker.gologin.com/v1/scrape?${params}`, {
headers: { apikey: process.env.GOLOGIN_SCRAPING_API_KEY },
});
const page = response.ok ? (await response.json()).data?.html : '';
if (page?.includes(marker)) return page;
await new Promise((resolve) => setTimeout(resolve, 5000));
}
throw new Error(`Nothing came back for ${url}, try again later`);
}
const text = (markup = '') => markup.replace(/<[^>]+>/g, ' ').replace(/&/g, '&').replace(/'/g, "'").replace(/\s+/g, ' ').trim();
const key = (job) => `${job.company} ${job.title}`.toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
const linkedin = await scrape(`https://www.linkedin.com/jobs/search?${new URLSearchParams({ keywords: query, location: city })}`, 'urn:li:jobPosting:');
const fromLinkedin = linkedin
.split('<li')
.filter((card) => card.includes('urn:li:jobPosting:'))
.map((card) => ({
board: 'LinkedIn',
title: text(card.match(/base-search-card__title[^>]*>([\s\S]*?)<\/h3>/)?.[1]),
company: text(card.match(/base-search-card__subtitle[^>]*>([\s\S]*?)<\/h4>/)?.[1]),
location: text(card.match(/job-search-card__location[^>]*>([\s\S]*?)<\/span>/)?.[1]),
url: `https://www.linkedin.com/jobs/view/${card.match(/urn:li:jobPosting:(\d+)/)[1]}`,
}));
const indeed = await scrape(`https://www.indeed.com/jobs?${new URLSearchParams({ q: query, l: city, limit: 50 })}`, 'mosaic-provider-jobcards"]=');
const start = indeed.indexOf('=', indeed.indexOf('mosaic-provider-jobcards"]=')) + 1;
const cards = JSON.parse(indeed.slice(start, indeed.indexOf(';\n', start)));
const results = cards.metaData.mosaicProviderJobCardsModel.results;
const fromIndeed = results.filter((job, i) => results.findIndex((other) => other.jobkey === job.jobkey) === i).map((job) => ({
board: 'Indeed',
title: job.title,
company: job.company,
location: job.formattedLocation,
url: `https://www.indeed.com/viewjob?jk=${job.jobkey}`,
}));
const jobs = new Map();
for (const job of [...fromLinkedin, ...fromIndeed]) {
const seen = jobs.get(key(job));
if (seen) seen.boards.add(job.board);
else jobs.set(key(job), { ...job, boards: new Set([job.board]) });
}
const onBoth = [...jobs.values()].filter((job) => job.boards.size === 2);
console.log(`LinkedIn ${fromLinkedin.length} + Indeed ${fromIndeed.length} = ${jobs.size} different jobs, ${onBoth.length} on both boards, 2 pages billed`);
for (const job of onBoth.slice(0, 5)) console.log(`${job.title} | ${job.company} | ${job.location}`);准备好用在自己的搜索上了吗?获取 API 密钥和免费请求额度。
LinkedIn 没有面向您应用的职位搜索 API,现成的职位采集工具按每个职位计费,免费的职位爬虫库则需要您自备代理。下面是各条路线获取同样职位所需的条件。
| 需要什么 | JobSpy | Apify | Bright Data | |
|---|---|---|---|---|
| 您按什么付费 | 一页 | 您的代理 | 每个职位 | 每条记录 |
| 来自搜索的 10,000 个 LinkedIn 职位 | $0.16 | 免费 + 代理 | $10 | $15 |
| 每个计费单位的职位数 | 60 | 无 | 1 | 1 |
| 整个页面的 HTML 或 Markdown | 是 | 否 | 否 | 否 |
| 无需自备代理即可运行 | 是 | 否 | 是 | 是 |
| 免费开始 | 1,000 个页面 | 免费 | 每月 $5 | 5,000 条记录 |
要深入采集某一个招聘网站?请查看 Indeed 爬虫,或用 Web Unlocker 以同样的价格采集任何其他站点。
一个账户,一个代理网络,一套生态。按任务需要选择产品。
还要采集其他站点?请查看 Indeed、Google Maps 和 Reddit 采集工具,或全部网页采集工具。
一种加载招聘网站页面并把职位提取为数据的程序:标题、公司、地点、薪资、发布日期、描述和链接。使用 Web Unlocker,加载这一步就是每页一次 API 调用,LinkedIn、Indeed 和公司招聘页都一样,保留哪些字段由您决定。
您的脚本请求招聘网站的搜索页面,读取上面的职位卡片,需要完整描述时再顺着每张卡片打开职位自己的页面。Web Unlocker 从您选择的国家用真实浏览器加载每个页面并返回 HTML,您的代码只需解析。
网页抓取招聘信息,要从访客会进行的搜索开始,即职位名称和地点。把它的地址发送给 Web Unlocker。LinkedIn 搜索页返回 60 个职位,Indeed 页面返回 50 个,每个都带有标题、公司、地点和日期。上面的代码正是用 Python 和 Node.js 这样做的。
招聘网站和聚合平台把许多网站的职位汇总到一次搜索中。猎头公司和销售团队关注哪些公司在招聘、招什么岗位。分析师按岗位和城市追踪薪资与需求,求职 AI 智能体把人和新职位匹配起来。他们需要的都一样:今天的职位页面。
可以。LinkedIn 职位抓取适用于公开页面:职位搜索和职位页面无需登录即可打开,第一页搜索结果列出 60 个职位,后续每页 10 个,职位页面带有完整描述、职级、雇佣类型和申请人数。Web Unlocker 按访客看到的样子返回它们。
没有用于读取职位搜索结果的 LinkedIn 职位 API 或 LinkedIn 职位搜索 API。LinkedIn 的 Job Posting API 面向向 LinkedIn 发布职位的合作伙伴,而且目前不接受新的合作伙伴。要读取公开的职位信息,职位爬虫会加载访客打开的同样页面。
要从 LinkedIn 抓取职位,用 requests 库把搜索地址发送给职位爬虫 API,把页面拆分为职位卡片,再从每张卡片读取标题、公司、地点和日期。上面的 Python 标签页是一份完整的 Python 版 LinkedIn 职位爬虫,已在真实 API 上测试过:一次请求得到 60 个职位。
LinkedIn 会对来自同一地址的短时间大量请求返回错误,通常在大约十页之后,所以在一台服务器上运行的脚本会停在那里。Web Unlocker 用真实浏览器加载每个页面,使用您所选国家的住宅 IP。Node.js 标签页把一次搜索读到了最后:67 页,660 个职位。
在我们的测试中,LinkedIn、Indeed、Dice、Wellfound、Built In 和 SimplyHired 的搜索页面都返回了,Lever、Ashby、Greenhouse 和 Workday 上的公司招聘页也是如此。Glassdoor 和 ZipRecruiter 从美国地址无法稳定返回,所以我们没有列出它们。
通过 Web Unlocker 打开职位自己的页面:linkedin.com/jobs/view/ 加上职位 ID,或 Indeed 的职位页面。它会返回描述以及标题、公司、地点和发布日期。每个职位一页,1,000 条描述只需 $0.98。
能。请求 Markdown 格式,Web Unlocker 就会把职位页面作为文本返回,可直接交给智能体或 Claude。Gologin scraping skill 让 Claude 替您调用它,MCP & AI Skills 则能把一句普通的需求变成一个可用的职位爬虫。
职位信息本来就是供人阅读的,职位爬虫读取的是访客无需登录就能看到的公开页面。各国规则不同,也取决于您如何使用这些数据,所以请对照规则核对您自己的用法。Web Unlocker 返回页面,采集什么由您决定。
职位爬虫 API 每 1,000 个页面低于 $1,每个招聘网站价格相同。一个 LinkedIn 搜索页包含 60 个职位,所以来自搜索页的 10,000 个职位只需 16 美分。页面加载失败不收费。套餐每月 $49 起,含 50,000 次请求。
有,可以免费开始:Web Unlocker 附带 1,000 次免费请求,足够从搜索页面获取 60,000 个 LinkedIn 职位,或 1,000 条完整的职位描述。开源的职位爬虫库也是免费的,代理则由您自己提供并维护。
这取决于您的需求。Apify 和 Bright Data 等职位采集服务和职位数据 API 出售整理好的现成数据行,并把每个职位按一条记录计费;免费的职位采集软件需要您自备代理。Web Unlocker 是一个以单一价格返回整个页面的职位爬虫 API,适用于任何招聘网站,所以保留哪些字段由您决定。
JobSpy 是免费的开源 Python 库,支持 LinkedIn、Indeed、Glassdoor 和 ZipRecruiter。它在您自己的机器上运行,代理需要您自己准备和维护,而且它自己的说明也提到 LinkedIn 会对短时间内的大量请求返回错误。Web Unlocker 自带网络并返回页面,您只为成功返回的页面付费。
Apify 上的 LinkedIn 职位爬虫返回现成的数据行,并按每个职位计费,每 1,000 个职位 $1 起。Web Unlocker 按页计费:一个 LinkedIn 搜索页包含 60 个职位,所以 10,000 个职位只需 16 美分,再用几行代码(就像上面的标签页)切出字段即可。
简单介绍一下您的团队,即可获得: