mcpField
J
JobSpy

JobSpy

本地服务
github.com商业与营销4.6k1 天前更新

关于 JobSpy

JobSpy 是面向开发者和求职者的职位抓取工具及 MCP 服务,可并发汇总多个招聘网站的职位,并以 dataframe 返回结果。

主要功能

  1. 01并发抓取多个招聘网站
  2. 02以 dataframe 汇总职位信息
  3. 03支持代理以应对请求拦截
  4. 04提供搜索与输出选项的命令行工具

适用场景

  1. 01汇总多个招聘网站的职位
  2. 02按职位名称和地点搜索
  3. 03将筛选结果保存为 JSONL

MCP 相关

`mcp-jobspy` MCP 服务向 MCP 客户端提供 JobSpy 职位搜索抓取功能,可通过 `uvx mcp-jobspy@latest` 启动。

配置

本地服务的配置在各客户端中通用,复制后粘贴到客户端的 MCP 配置文件即可。

mcp.json · 通用配置
{
"mcpServers": {
"speedyapply-jobspy": {
"command": "uvx",
"args": [
"mcp-jobspy"
]
}
}
}
启动命令uvx mcp-jobspy

本地服务需要在你的电脑上安装运行环境(如 Node.js 18+)。各客户端的配置文件位置不同,请参考客户端文档。

安装包
pypimcp-jobspy1.4.1

工具

2

收录的工具列表 · 更新于 5 天前

参数类型必填说明
offsetinteger否跳过每个网站的前 N 条结果。
ca_certany否代理的 CA bundle 文件路径。
proxiesany否要轮换使用的代理 URL,例如 http://user:pass@host:port;可提供一个 URL 或列表。
save_toany否还将此搜索的每条记录保存到此文件:按名称指定 .csv、.json 或 .jsonl。
distanceinteger否距所在位置的英里数。
job_typeany否就业类型。
locationany否城市、州或国家/地区。
hours_oldany否最近 N 小时内发布。
is_remoteboolean否仅限远程职位。
site_nameany否要搜索的职位网站。默认值: indeed、linkedin、zip_recruiter、glassdoor。区域性网站: bayt(中东)、naukri(印度)、bdjobs(孟加拉国)、hellowork(法国)。
easy_applyboolean否仅限可直接在职位网站上申请的职位。
user_agentany否要发送的 User-Agent 标头。
search_termany否关键词,例如 'nurse'。
country_indeedstring否Indeed 和 Glassdoor 的国家/地区,例如 'uk'。
results_wantedinteger否每个网站的结果数。
fetch_descriptionboolean否还要读取每个职位的页面以获取其描述。只有 Indeed 会在搜索结果中返回描述;其他网站会为每个职位额外发起一个请求,速度较慢,也更容易被拦截。
description_formatany否描述文本的格式。
linkedin_company_idsany否将 LinkedIn 搜索限定为指定公司的 LinkedIn 公司 ID。
enforce_annual_salaryboolean否将小时、日、周和月薪酬转换为年薪。

详细介绍

JobSpy

PyPI 版本 Python 版本 每月下载量 CI 许可证:MIT Discord

JobSpy 是一个职位抓取库,可通过一个工具汇总热门招聘网站上的职位:

  • 并发抓取 LinkedIn、Indeed、Glassdoor、ZipRecruiter、Bayt、Naukri、BDJobs 和 HelloWork 上的职位信息
  • 将职位信息汇总到数据框中
  • 支持代理,以绕过屏蔽

JobSpy 演示

安装

pip install -U python-jobspy

需要 Python 版本 >= 3.10

用法

from jobspy import scrape_jobs

jobs = scrape_jobs(
    site_name=["indeed", "linkedin", "zip_recruiter", "glassdoor"],  # also "bayt", "naukri", "bdjobs", "hellowork"
    search_term="software engineer",
    location="San Francisco, CA",
    results_wanted=20,
    hours_old=72,
    country_indeed="USA",
    # fetch_description=True,  # read each job's page on boards whose search results have no description (slower)
    # proxies=["user:pass@host:port", "localhost"],
)
print(f"Found {len(jobs)} jobs")
print(jobs.head())
jobs.to_csv("jobs.csv", index=False)

输出

SITE           TITLE                             COMPANY           LOCATION                JOB_TYPE  INTERVAL  MIN_AMOUNT  MAX_AMOUNT  JOB_URL                                            DESCRIPTION
indeed         Software Engineer                 AMERICAN SYSTEMS  Arlington, VA, USA      None      yearly    150000      200000      https://www.indeed.com/viewjob?jk=5e409e577046...  THIS POSITION COMES WITH A 10K SIGNING BONUS!...
indeed         Senior Software Engineer          TherapyNotes.com  Philadelphia, PA, USA   fulltime  yearly    110000      135000      https://www.indeed.com/viewjob?jk=da39574a40cb...  About Us TherapyNotes is the national leader i...
linkedin       Software Engineer - Early Career  Lockheed Martin   Sunnyvale, CA, USA      fulltime  yearly    None        None        https://www.linkedin.com/jobs/view/3693012711      Description:By bringing together people that u...
linkedin       Full-Stack Software Engineer      Rain              New York, NY, USA       fulltime  yearly    None        None        https://www.linkedin.com/jobs/view/3696158877      Rain’s mission is to create the fastest and ea...
zip_recruiter  Software Engineer - New Grad      ZipRecruiter      Santa Monica, CA, USA   fulltime  yearly    130000      150000      https://www.ziprecruiter.com/jobs/ziprecruiter...  We offer a hybrid work environment. Most US-ba...
zip_recruiter  Software Developer                TEKsystems        Phoenix, AZ, USA        fulltime  hourly    65          75          https://www.ziprecruiter.com/jobs/teksystems-0...  Top Skills' Details• 6 years of Java developme...

命令行

此软件包会安装一个 jobspy 命令,其选项与下方 scrape_jobs() 的参数一致;运行 jobspy -h 可查看选项、输出字段和退出代码。

uv tool install python-jobspy

jobspy "software engineer" --site indeed,linkedin --location Chicago -n 20
jobspy nurse --site indeed,linkedin --hours-old 24 -o jobs.jsonl
jobspy "data analyst" --remote --fields title,company,job_url

MCP 服务

mcp-jobspy 是一个通过 uvx mcp-jobspy@latest 运行的 MCP 服务。有关配置、工具和代理的信息,请参阅 mcp/README.md。

标准配置适用于大多数客户端:

{
  "mcpServers": {
    "jobspy": {
      "command": "uvx",
      "args": ["mcp-jobspy@latest"]
    }
  }
}

scrape_jobs() 的参数

Optional
├── site_name (list|str): 
|    linkedin, zip_recruiter, indeed, glassdoor, google, bayt, bdjobs, naukri, hellowork
|    (default is all)
│
├── search_term (str)
|
├── google_search_term (str)
|     search term for google jobs. This is the only param for filtering google jobs.
│
├── location (str)
│
├── distance (int): 
|    in miles, default 50
│
├── job_type (str): 
|    fulltime, parttime, contract, temporary, internship, perdiem, other, volunteer
│
├── proxies (list|str): 
|    in format ['user:pass@host:port', 'localhost'], or a single proxy as a string
|    each job board scraper will round robin through the proxies
|    socks proxies on LinkedIn, Indeed and BDJobs need pip install "requests[socks]"
|
├── is_remote (bool)
│
├── results_wanted (int): 
|    number of job results to retrieve for each site specified in 'site_name'
│
├── easy_apply (bool): 
|    filters for jobs that are hosted on the job board site
|
├── user_agent (str): 
|    override the default user agent which may be outdated
│
├── description_format (str): 
|    markdown, html, plain (Format type of the job descriptions. Default is markdown.)
│
├── offset (int): 
|    skips that many results (e.g. 25 skips the first 25 and starts from the 26th)
│
├── hours_old (int): 
|    filters jobs by the number of hours since the job was posted 
|    (Glassdoor filters by whole days, so it rounds up to the next day.)
│
├── verbose (int) {0, 1, 2}: 
|    Controls the verbosity of the runtime printouts 
|    (0 prints only errors, 1 is errors+warnings, 2 is all logs. Default is 1.)
│
├── fetch_description (bool): 
|    for boards whose search results don't include the job description: fetches each job's
|    page for the description and other details (e.g. job type). Without it these are empty
|    for those boards. Adds one request per job, so use proxies for larger searches
│
├── linkedin_fetch_description (bool): 
|    deprecated, use fetch_description (still works; removed in 2.0)
│
├── linkedin_company_ids (list[int]): 
|    searches for linkedin jobs with specific company ids
|
├── country_indeed (str): 
|    filters the country on Indeed & Glassdoor (default is usa; see below for the names)
|
├── enforce_annual_salary (bool): 
|    converts wages to annual salary
|
├── ca_cert (str)
|    path to CA Certificate file for proxies

支持职位搜索的国家/地区

LinkedIn

LinkedIn 支持全球搜索,且只使用 location 参数。

ZipRecruiter

ZipRecruiter 搜索美国/加拿大的职位,且只使用 location 参数。

Indeed / Glassdoor

Indeed 和 Glassdoor 支持大多数国家/地区,可通过 country_indeed 参数选择(默认值为 usa)。此外,可使用 location 参数缩小搜索范围,例如在需要时指定城市和州。

在 Indeed 上搜索时,可指定以下国家/地区(请使用准确名称,* 表示支持 Glassdoor):

Argentina*Australia*Austria*Bahrain
Belgium*Brazil*Canada*Chile
ChinaColombiaCosta RicaCzech Republic
DenmarkEcuadorEgyptFinland
France*Germany*GreeceHong Kong*
HungaryIndia*IndonesiaIreland*
IsraelItaly*JapanKuwait
LuxembourgMalaysia*Mexico*Morocco
Netherlands*New Zealand*NigeriaNorway
OmanPakistanPanamaPeru
PhilippinesPolandPortugalQatar
RomaniaSaudi ArabiaSingapore*South Africa
South KoreaSpain*SwedenSwitzerland*
TaiwanThailandTurkeyUkraine
United Arab EmiratesUK*USA*Uruguay
VenezuelaVietnam*
Bayt

Bayt 会搜索所有国家/地区,除非 location 指定了其覆盖的地区,例如 "Dubai, UAE" 或 "Saudi Arabia"。

BDJobs

BDJobs 会搜索孟加拉国。location 可填写行政区或地区,例如 "Dhaka" 或 "Chattogram Division"。

Naukri

Naukri 会搜索印度。location 可填写城市,例如 "Pune"。

HelloWork

HelloWork 会搜索法国。location 可填写法国城市、邮政编码或地区,例如 "Lyon"。大多数职位信息使用法语发布,因此使用法语搜索词能找到更多结果。

备注

  • 目前 Indeed 是最好的抓取工具,且没有速率限制。
  • Indeed 的 date_posted 是职位添加到 Indeed 的日期,与 hours_old 筛选所依据的日期相同。
  • 大多数招聘网站接口在单次搜索中最多返回约 1000 个职位。
  • LinkedIn 会对突发请求进行速率限制,并返回 429;约一分钟后限制会解除。进行大规模搜索时请使用代理。
  • Glassdoor 每秒请求超过约 2 次时会进行速率限制。

常见问题

问:如何区分被屏蔽的招聘网站和没有职位的招聘网站?
**答:**发生故障和忽略选项时会记录日志,结果的 attrs 也会包含相同消息,供代码读取:

jobs.attrs["errors"]    # {"linkedin": "response status code 429 (blocked: use a proxy)"}
jobs.attrs["warnings"]  # {"bdjobs": ["job_type internship isn't supported, ignoring it"]}

问:为什么 Indeed 会返回无关职位?
**答:**Indeed 也会搜索职位描述。

  • 使用 - 排除词语
  • 使用 "" 进行精确匹配

Indeed 搜索词示例

search_term='"engineering intern" software summer (java OR python OR c++) 2025 -tax -marketing'

此搜索会检索职位描述和标题,且必须包含 software、summer、2025、其中一种语言,以及精确匹配的 engineering intern,同时不得包含 tax 和 marketing。


问:使用 "google" 时没有结果?
**答:**Google Jobs 目前不可用。


问:收到响应代码 429?
**答:**招聘网站因请求过多而屏蔽了你。所有招聘网站都会积极屏蔽请求。我们建议:

  • 每次抓取之间等待一段时间(因网站而异)。
  • 尝试使用 proxies 参数更改 IP 地址。

JobPost 架构

JobPost
├── id
├── site
├── job_url
├── job_url_direct
├── title
├── company
├── location
├── date_posted
├── job_type: fulltime, parttime, internship, contract, temporary, ...
├── salary_source: direct_data, description (parsed from posting)
├── interval: yearly, monthly, weekly, daily, hourly
├── min_amount
├── max_amount
├── currency
├── is_remote
├── job_level
├── job_function
├── listing_type
├── emails
├── description
├── company_industry
├── company_url
├── company_logo
├── company_url_direct
├── company_addresses
├── company_num_employees
├── company_revenue
├── company_description
├── skills
├── experience_range
├── company_rating
├── company_reviews_count
├── vacancy_count
└── work_from_home_type

如果招聘网站未提供某一列,该列将为空。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。