JobData/docs/爬虫数据上报接口文档.md
2026-03-22 23:22:30 +08:00

15 KiB
Raw Permalink Blame History

爬虫数据上报接口文档

适用版本JobData v1.x 更新日期2026-03-20 目标读者:接手爬虫开发或后端对接的工程师


目录

  1. 整体架构
  2. 认证方式
  3. 核心上报接口
  4. 各平台数据结构
  5. 去重规则
  6. 爬虫调用示例
  7. 辅助接口
  8. 数据存储说明
  9. 常见问题

1. 整体架构

爬虫Boss / 前程无忧 / 智联)
        │
        │  POST /api/v1/universal/data/batch-store-async
        ▼
   FastAPI 后端app/
        │
        ├── 去重检查ClickHouse 查最近 90 天)
        ├── 写入 ClickHousejob_data 库)
        └── 转发至外部数据平台qixin.com

三个平台的爬虫调用同一套接口,通过 platform 字段区分来源,通过 data_type 字段区分数据类型(职位/公司)。


2. 认证方式

数据上报接口属于内部接口,无需鉴权

爬虫调用时统一在 Header 中携带:

token: dev

说明:dev 是开发模式 Token后端不验证签名直接放行。生产部署如需启用鉴权改用 JWT TokenHS256有效期 7 天)。


3. 核心上报接口

Base URL(本地开发):http://localhost:8000

两个路径前缀完全等价,行为相同:

  • /api/v1/universal
  • /api/v1/job

3.1 异步批量上报(推荐)

三个平台爬虫均使用此接口,立即返回 202后台异步写入。

POST /api/v1/universal/data/batch-store-async

Request Headers

Content-Type: application/json
token: dev

Request Body

{
    "data_list": [
        { ...原始职位或公司 JSON... }
    ],
    "data_type": "job",
    "platform": "boss",
    "check_duplicate": true
}
字段 类型 必填 说明
data_list List[Dict] 原始数据列表,结构见第 4 节
data_type string job(职位)或 company(公司)
platform string boss / qcwy / zhilian
check_duplicate bool 默认 truefalse 时跳过去重直接写入

ResponseHTTP 202

{
    "code": 202,
    "message": "批量数据已加入异步处理队列,共 10 条",
    "platform": "boss",
    "data_type": "job"
}

3.2 同步批量上报

同步等待全部写入完成后返回,可获得详细的成功/失败统计。

POST /api/v1/universal/data/batch-store

Request Body — 与 3.1 相同。

ResponseHTTP 200

{
    "code": 200,
    "message": "批量处理完成: 成功 8 条,失败 0 条,重复 2 条",
    "data": {
        "total": 10,
        "success": 8,
        "failed": 0,
        "duplicate": 2,
        "errors": []
    },
    "platform": "boss",
    "data_type": "job"
}

3.3 同步单条上报

POST /api/v1/universal/data/store

Request Body

{
    "data": { ...单条原始 JSON... },
    "data_type": "job",
    "platform": "boss",
    "check_duplicate": true
}

注意:字段名是 data(单条),不是 data_list

ResponseHTTP 200

{
    "code": 200,
    "message": "JSON数据存储成功",
    "data": {
        "success": true,
        "message": "JSON数据存储成功",
        "duplicate": false,
        "table_name": "boss_job",
        "storage_type": "json"
    },
    "platform": "boss",
    "data_type": "job"
}

数据重复时 duplicatetruemessage"数据重复,跳过插入"HTTP 仍返回 200。


3.4 平台专属便捷接口

Request Body 直接传原始 JSON 对象(无需包装 platform/data_type),等价于 3.3 的 data 字段:

URL 平台 类型
POST /api/v1/job/boss/job BOSS直聘 职位
POST /api/v1/job/boss/company BOSS直聘 公司
POST /api/v1/job/qcwy/job 前程无忧 职位
POST /api/v1/job/qcwy/company 前程无忧 公司
POST /api/v1/job/zhilian/job 智联招聘 职位
POST /api/v1/job/zhilian/company 智联招聘 公司

4. 各平台数据结构

以下为 data_list 中每个元素的结构,即各平台原始 API 响应体(直接透传,无需转换)。


4.1 BOSS直聘platform=boss

职位data_type=job

数据来源BOSS 微信小程序接口 /wapi/zpgeek/miniapp/job/detail.json

{
    "jobBaseInfoVO": {
        "jobId": "123456",
        "encryptJobId": "abc123",
        "positionName": "Python 工程师",
        "locationName": "上海",
        "locationDesc": "上海市浦东新区XX路XX号",
        "jobDesc": "负责数据采集与处理...",
        "degreeName": "本科",
        "experienceName": "3-5年",
        "lowSalary": 15,
        "highSalary": 25,
        "requiredSkills": ["Python", "爬虫", "ClickHouse"],
        "salaryWelfareInfo": ["五险一金", "弹性工作"]
    },
    "brandComInfoVO": {
        "encryptBrandId": "brand_abc",
        "brandName": "某科技有限公司",
        "industryName": "互联网",
        "scaleName": "100-499人",
        "introduce": "公司简介..."
    },
    "bossBaseInfoVO": {
        "brandName": "张HR"
    }
}

关键去重字段jobBaseInfoVO.jobId

公司data_type=company

数据来源BOSS 微信小程序接口 /wapi/zpgeek/miniapp/brand/detail.json

{
    "name": "某科技有限公司",
    "companyFullInfoVO": {
        "name": "某科技有限公司(全称)"
    }
}

关键去重字段namecompanyFullInfoVO.name(取 company_name


4.2 前程无忧platform=qcwy

职位data_type=job

数据来源:前程无忧 APP 接口

{
    "jobId": "JL123456789",
    "updateDateTime": "2026-03-20 10:00:00",
    "jobName": "数据工程师",
    "companyName": "某公司",
    "fullCompanyName": "某公司全称有限公司",
    "coId": "CO123456",
    "jobDescribe": "岗位职责:...",
    "degreeString": "本科",
    "workYearString": "3-5年",
    "jobSalaryMax": 20000,
    "jobSalaryMin": 15000,
    "provideSalaryString": "15k-20k",
    "termStr": "全职",
    "companySizeString": "500-999人",
    "companyTypeString": "民营企业",
    "major1Str": "互联网/电子商务",
    "major2Str": "数据服务",
    "jobWelfareCodeDataList": [
        { "chineseTitle": "五险一金", "typeTitle": "社保", "code": "001" }
    ],
    "jobTagsForOrder": ["Python", "Spark", "Hive"],
    "location": "上海",
    "workLocation": {
        "workAddress": "浦东新区",
        "address": "上海市浦东新区XX路"
    },
    "jobAreaString": "上海",
    "jobAreaLevelDetail": {
        "cityString": "上海",
        "landMarkString": "陆家嘴"
    },
    "confirmDateString": "2026-03-20",
    "jobHref": "https://www.51job.com/...",
    "companyHref": "https://www.51job.com/..."
}

关键去重字段jobId + updateDateTime(两字段联合唯一)

公司data_type=company

{
    "companyName": "某公司",
    "fullCompanyName": "某公司全称有限公司"
}

关键去重字段companyName


4.3 智联招聘platform=zhilian

职位data_type=job

数据来源:智联招聘 PC 搜索接口 https://fe-api.zhaopin.com/c/i/search/positions

{
    "number": "ZL20260320001",
    "firstPublishTime": "2026-03-20T10:00:00",
    "name": "后端开发工程师",
    "jobId": "J001",
    "companyName": "某公司",
    "companyId": "C001",
    "salary60": "15k-25k",
    "jobSummary": "职位描述:负责后端服务开发...",
    "education": "本科",
    "workingExp": "3-5年",
    "workType": "全职",
    "workCity": "上海",
    "cityDistrict": "浦东新区",
    "companySize": "500-999人",
    "propertyName": "民营企业",
    "industryName": "互联网",
    "skillLabel": [
        { "value": "Go" },
        { "value": "Python" }
    ],
    "recruitNumber": 3,
    "positionURL": "https://www.zhaopin.com/...",
    "companyUrl": "https://www.zhaopin.com/...",
    "companyDesc": "公司描述(从额外接口补充)"
}

关键去重字段number + firstPublishTime(两字段联合唯一)

公司data_type=company

{
    "companyName": "某公司",
    "name": "某公司"
}

关键去重字段companyNamename


5. 去重规则

平台 数据类型 去重字段 ClickHouse 表
boss job jobBaseInfoVO.jobId boss_job
boss company name / companyFullInfoVO.name boss_company
qcwy job jobId + updateDateTime qcwy_job
qcwy company companyName qcwy_company
zhilian job number + firstPublishTime zhilian_job
zhilian company companyName / name zhilian_company
  • 去重检查范围:最近 90 天内已入库的记录。
  • 重复数据不报错,正常返回 200duplicate: true
  • check_duplicate: false 可跳过去重,强制写入(测试时使用)。

6. 爬虫调用示例

BOSS直聘jobs_spider/boss/boos_api.py

import requests

API_BASE_URL = "http://localhost:8000"

def push_job(zp_data: dict):
    """推送职位数据"""
    payload = {
        "data_list": [zp_data],
        "data_type": "job",
        "platform": "boss"
    }
    resp = requests.post(
        f"{API_BASE_URL}/api/v1/universal/data/batch-store-async",
        headers={
            "accept": "application/json",
            "token": "dev",
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=30
    )
    return resp.json()


def push_company(zp_data: dict):
    """推送公司数据"""
    payload = {
        "data_list": [zp_data],
        "data_type": "company",
        "platform": "boss"
    }
    resp = requests.post(
        f"{API_BASE_URL}/api/v1/universal/data/batch-store-async",
        headers={
            "accept": "application/json",
            "token": "dev",
            "Content-Type": "application/json"
        },
        json=payload,
        timeout=30
    )
    return resp.json()

前程无忧(jobs_spider/qcwy/qcwy.py

import requests
import socket

API_BASE_URL = "http://localhost:8000"
local_ip = socket.gethostbyname(socket.gethostname())

def report_data(data: list, data_type: str = "job"):
    """批量上报数据"""
    payload = {
        "data_list": data,
        "data_type": data_type,   # "job" 或 "company"
        "platform": "qcwy"
    }
    resp = requests.post(
        f"{API_BASE_URL}/api/v1/universal/data/batch-store-async",
        json=payload,
        headers={
            "accept": "application/json",
            "Content-Type": "application/json",
            "X-Forwarded-For": local_ip   # 传递真实 IP用于日志溯源
        },
        timeout=300
    )
    return resp.json()

智联招聘(jobs_spider/zhilian/zhilian_single.py

import requests

API_BASE_URL = "http://localhost:8000"

def report_data(data_list: list, data_type: str = "job"):
    """批量上报数据"""
    payload = {
        "data_list": data_list,
        "data_type": data_type,   # "job" 或 "company"
        "platform": "zhilian"
    }
    resp = requests.post(
        f"{API_BASE_URL}/api/v1/universal/data/batch-store-async",
        json=payload,
        headers={
            "accept": "application/json",
            "Content-Type": "application/json"
        },
        timeout=300
    )
    return resp.json()

7. 辅助接口

爬虫运行过程中还会调用以下辅助接口:

接口 说明 主要使用方
GET /api/v1/token/tokens?page=1&page_size=10 获取可用的 MPT Token 列表 BOSS爬虫
GET /api/v1/keyword/available?source=boss&limit=1&reserve=True 获取下一个未使用的关键词(城市+职位组合) BOSS爬虫
POST /api/v1/keyword/mark-used 标记关键词已使用 BOSS爬虫
GET /api/v1/stats 查询各平台已入库数据量 监控/运营
GET /api/v1/platforms 查询支持的平台列表及去重字段配置 调试
GET /api/v1/universal/data?platform=boss&data_type=job&page=1&page_size=20 分页查询已入库数据 调试

标记关键词已使用 Request Body

{
    "source": "boss",
    "ids": [1, 2, 3]
}

8. 数据存储说明

ClickHouse 表结构

所有表均在 job_data 数据库下ENGINE = MergeTree()

通用列(每张表都有):

列名 类型 说明
id UInt64 自增 ID
json_data String 原始 JSON 字符串(完整保存)
created_at DateTime 入库时间
updated_at DateTime 更新时间

各表额外列(用于去重查询):

表名 额外列
boss_job job_id String
boss_company company_name String
qcwy_job job_id String, update_date_time String
qcwy_company company_name String
zhilian_job number String, first_publish_time String
zhilian_company company_name String

统一查询视图

job_analytics 视图 UNION ALL 三张职位表,提供统一查询入口:

列名 说明
source 平台来源boss/qcwy/zhilian
job_id 职位唯一标识
position_name 职位名称
company_name 公司名称
salary_text 薪资描述
city 城市
experience_required 经验要求
education 学历要求
created_at 入库时间

9. 常见问题

Q上报返回 202但数据库里查不到数据 A异步接口的写入有延迟通常 1-5 秒)。改用同步接口 batch-store 可立即确认写入结果。

Q如何判断某条数据是否已存在 A调用同步单条上报接口响应中 duplicate: true 表示已存在。

Qcheck_duplicate: false 会导致重复数据吗? A会。仅在测试/调试时使用,生产环境保持默认 true

Q三个平台的数据结构差异大如何统一分析 A使用 job_analytics 视图,已将三张表的字段映射为统一列名。

Q爬虫报超时错误怎么处理 A异步接口 timeout 建议设 30s同步接口因要等待写入完成建议设 300s。若仍超时检查 ClickHouse 连接状态。

Qtoken: dev 在生产环境安全吗? A不安全。生产环境应替换为 JWT Token并在接口上挂载鉴权中间件。


文档由 JobData 项目自动生成,如有疑问联系项目维护者。