资讯动态

AI求职助手get_jobs:自动化岗位采集与智能匹配实践

发布时间:2026/10/20 9:03:46 来源:尧图企业网站定制
1. 先想清楚get_jobs 这个 AI 助手要替我做哪几件事1.1 传统求职过程的三个低效环节常年在招聘软件里翻岗位的人应该都有同感真正让人心累的往往不是面试本身而是面试之前那个漫长的找岗位阶段。第一个低效环节是岗位获取太分散。主流招聘站点我至少注册了四五个每个平台的推荐算法又有各自主见同一个岗位换个标题就能出现两三次我对它的印象永远停留在好像在哪儿见过。第二个低效环节是 JD 阅读成本极高。一条正常岗位描述动辄几百上千字真正关键的信息——技术栈、年限、学历、薪资区间、是否急招——全部埋在宣传性质的废话里。一天认真读完二十条 JD精力就见底了更别提还要逐个对照自己的简历做匹配判断。第三个低效环节最隐蔽简历和 JD 的匹配全凭感觉。我投了二三十个岗位以后甚至记不清哪些岗位写了全日制本科这种硬性门槛哪些岗位明确要求五年以上经验更别说针对不同岗位微调简历侧重点。这三个问题叠加结果就是合适的岗位被湮没在信息噪声里而我的精力全部消耗在机械劳动上。我也试过现成的工具但要么绑定单一平台要么要求把简历托管给第三方数据安全和定制自由度完全不符合要求。与其将就不如自己动手——这就是 get_jobs 的由来。1.2 get_jobs 的能力清单与模块边界动手写代码之前我先把需求列成了一份清单防止项目越写越大最后变成收不了尾的玩具。最后圈定的能力是下面五块岗位采集从配置好的职位源定时拉取新增岗位自动去重并落库。JD 结构化解析把原始职位描述交给大模型抽出技能要求、年限、学历、薪资、福利等字段形成统一的岗位画像。简历画像维护把自己的技能、经历、求职偏好整理成结构化的档案方便随时更新。岗位匹配打分对每一条岗位画像和简历画像做相关性计算输出 0 到 100 分的匹配度以及推荐理由。结果通知把得分最高的几个岗位推送给我附带一段为什么推荐这个岗位的简要说明。同时我也在清单里明确了不做什么。get_jobs 不代替用户投递简历因为投递动作涉及简历版本管理和人工确认自动化投递省下的时间远抵不上误投带来的风险。它也不做任何需要登录用户账号才能完成的抓取那既违反平台规则又有账号安全风险。边界一旦定死整个系统的功能范围就收敛了后面所有环境配置和测试都围绕这五条主线展开不会东一榔头西一棒子。我的建议是如果你想做类似的东西一定要先做这份能力清单。get_jobs 能在一周内跑通第一版很大程度上就是因为模块间输入输出都定义死了采集器只负责输出去重后的原始 JD解析器只负责把原始 JD 变成岗位画像后面模块不关心前面的实现细节。2. 搭建前的技术选型哪些组件必须装、哪些可以省2.1 技术栈总览为什么是 Python 加轻量 Web 框架技术选型这一步我纠结过两个方案一是纯 Python 脚本加 JSON 文件存储简单但后续做界面和定时任务很别扭二是直接上完整的前后端分离架构功能强大但一个人维护成本太高。最后我选了中间路线核心逻辑用 Python展示层用 FastAPI 起一个轻量服务存储用 SQLite。Python 没什么好犹豫的网络请求、HTML 解析这类生态太成熟了大模型 SDK 和向量相关库也基本都是 Python 优先。Web 层选 FastAPI 而不是 Flask主要看中它对数据模型的原生校验支持配置文件和请求体的合法性检查能少写很多防御代码。前端我没有引入任何框架就是一个简单的 HTML 页面加几个接口调用毕竟工具是给自己用的界面能用就行。如果你对前端毫无兴趣甚至可以把界面整个去掉只用命令行输出 top 10 岗位那连 FastAPI 都不用装。下面是我的组件清单和可替换方案方便你按自己的情况裁剪组件get_jobs 方案可替代方案说明语言环境Python 3.113.10 最稳3.12 注意依赖兼容详见第 5 节踩坑Web 框架FastAPIFlask / 纯命令行不要界面就不装数据库SQLitePostgreSQL / DuckDB单机场景 SQLite 足够大模型服务大模型 API开启 JSON 模式本地开源模型本地部署吃显存向量计算模型返回的向量直接算余弦相似度专门向量数据库数据量小无需额外组件这个表帮我省掉了大量无关决策。比如向量数据库我最早也考虑过引入一个专用组件后来算了下get_jobs 每天新增岗位最多几百条全量累积也就几千条用 SQLite 存向量字符串、计算时一次性加载到内存做相似度性能绰绰有余完全没必要为此多维护一个服务。这算是只用必要组件原则的典型例子。2.2 职位数据入口合法数据源怎么选get_jobs 绕不开的一个问题是岗位数据从哪来。我调研过几条路线最终经验是数据源必须合法、稳定、可验证否则工具就是空中楼阁。第一类数据源是招聘平台的公开接口。有些站点提供开放 API 或者公开的职位聚合页这类接口通常有明确的频率限制和服务条款按文档调用就没有合规问题。我最初版本接了一个公开职位聚合接口字段很全包括职位名称、公司、薪资范围、技能标签省掉了大量解析工作。需要注意接口改版会导致字段变化代码里必须做兼容处理。第二类数据源是自己维护的种子职位列表。也就是把每天手动刷到的、觉得不错的岗位按统一格式粘贴到一个文本文件里get_jobs 负责解析和入库。这个方式看着土但稳定性最高也最适合起步阶段。第三类是利用订阅邮件或 RSS 推送。有些平台支持按关键词订阅新岗位邮件到达后让 get_jobs 定时解析收件箱新邮件缺点是要额外处理邮件格式。我在 get_jobs 里把数据源抽象成统一接口每类数据源实现一个抓取类外部只关心返回的岗位原始对象下游模块完全感知不到数据来源差异。这里提醒一句无论用哪类数据源都要先读平台服务条款控制请求频率不做绕过限制的行为。get_jobs 只获取公开信息绝不碰需要登录态的私有内容这是底线。2.3 模型选型效果、成本和本地部署的三方权衡岗位解析和匹配都依赖大模型所以模型选型要在环境配置前定下来。get_jobs 用到两类模型一类负责 JD 结构化解析的对话式大模型另一类负责生成简历和岗位向量表示的嵌入模型。第一类模型我选择直接调大模型 API而不是本地部署开源模型。原因很现实本地模型对显存有要求我手头只有一台日常办公电脑跑稍大参数量的开源模型推理速度太慢而 JD 解析一天要处理上百条文本速度直接影响使用体验。大模型 API 按调用量计费成本在可控范围。选服务商时我重点看两个能力一是是否支持 JSON 结构化输出二是能否配置随机性参数这两个对后续稳定性至关重要。第二类嵌入模型我用的是云端基础向量模型效果足够调用成本低。如果你希望完全离线运行也可以选本地嵌入模型这类模型通常参数量不大CPU 也能跑。有一个需要注意的点嵌入模型的向量维度要和存储字段保持一致中途换模型可能导致历史向量全部作废配置时就要想清楚。成本方面实测下来每天解析 100 条 JD 加生成 100 条岗位向量月成本大约相当于一顿工作餐的价格完全能接受。真正的成本黑洞往往不在解析本身而在调试阶段的重复调用这个第 5 节会专门讲控制方法。3. 环境配置完整记录从空目录到第一条真实职位入库3.1 Python 虚拟环境与依赖版本锁第一步就影响后面所有排错get_jobs 的环境配置听起来简单实际花掉的时间比写采集器还多。几乎所有问题的源头都出在依赖版本上所以第一步就是创建一个干净、隔离的 Python 环境。我直接用标准库自带的模块创建虚拟环境不需要额外装管理工具。在项目目录下执行mkdir get_jobs cd get_jobs python3 -m venv .venv source .venv/bin/activate有一个细节很多人忽略创建虚拟环境时用的 Python 版本决定了后面所有依赖的可选范围。我第一次用的是系统默认的较新版本结果安装某个数据处理库时连续报编译错误折腾了很久才发现这个库对新版本的支持还不稳定。如果你不想一上来就踩这个坑建议直接用 3.10 或 3.11 建环境。之后安装核心依赖pip install --upgrade pip pip install fastapi uvicorn requests beautifulsoup4 pydantic python-dotenv openai我没有一开始就把所有库列成巨大的 requirements.txt而是先装核心依赖按需再补。每装一个新库就做一次冒烟测试确认至少能导入成功。等所有模块跑通后再统一执行 pip freeze 把版本固化pip freeze requirements.lock.txt版本锁文件的价值会在长期开发中体现出来。过了一周你再打开项目或者换台机器继续开发直接按锁文件恢复环境可以保证行为一致避免在我电脑上是好的这类问题。环境配置不是一次性的它是整个项目的地基值得多花一点心思。3.2 .env 配置管理密钥、模型参数、路径都放哪get_jobs 里有几种信息不适合硬编码在代码里大模型 API 密钥、模型名称、数据库路径、采集间隔、日志级别。我用 .env 文件统一管理配合配置加载库在启动时读取。一个典型的 .env 文件长这样# 大模型 API 配置 LLM_API_KEYsk-xxxxx LLM_BASE_URLhttps://api.example.com/v1 LLM_MODELyour-llm-model-name LLM_TEMPERATURE0.1 # 向量模型配置 EMBED_MODELyour-embed-model-name EMBED_DIM1024 # 数据与存储 DB_PATH./data/get_jobs.db RAW_JOBS_DIR./data/raw_jobs # 运行参数 COLLECT_INTERVAL3600 LOG_LEVELINFO TOP_K5配置项里最容易忽略的是 LLM_TEMPERATURE。JD 解析是信息抽取不是创意写作随机性越高越容易输出格式不稳定的内容我设成 0.1。另外 .env 文件绝不能提交到代码仓库在 .gitignore 里加上这一行。为了让新环境容易初始化我同时维护了一份 .env.example 文件里面只有字段说明和占位符没有任何真实密钥。依赖环境变量还有一个隐藏好处代码里所有敏感信息不落地分享时也放心。我此前把项目打包发给朋友参考后来意识到压缩包里含 .env赶紧提醒对方删除并轮换密钥。这类工具密钥一旦泄露账号安全风险很大配置管理再怎么小心都不为过。3.3 数据库与存储为什么从 JSON 文件换成 SQLite最初我为了省事把解析后的岗位数据按 JSON 文件存放一个文件一个岗位。跑了三天我就换成 SQLite 了。岗位数据是强结构化的天然适合关系型存储查询、更新、去重都方便而且 SQLite 单文件、零运维备份就是复制一个文件。get_jobs 的表结构我一开始就设计成四张表CREATE TABLE jobs ( id INTEGER PRIMARY KEY AUTOINCREMENT, source TEXT NOT NULL, source_id TEXT NOT NULL UNIQUE, title TEXT NOT NULL, company TEXT, raw_text TEXT NOT NULL, url TEXT, published_at DATETIME, fetched_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE parsed_jds ( id INTEGER PRIMARY KEY AUTOINCREMENT, job_id INTEGER NOT NULL REFERENCES jobs(id), skills TEXT, years_min INTEGER, years_max INTEGER, education TEXT, salary_min INTEGER, salary_max INTEGER, advantages TEXT, summary TEXT, parsed_at DATETIME DEFAULT CURRENT_TIMESTAMP ); CREATE TABLE profile ( id INTEGER PRIMARY KEY CHECK (id 1), name TEXT, skills TEXT, experience TEXT, projects TEXT, preferences TEXT, updated_at DATETIME ); CREATE TABLE match_results ( id INTEGER PRIMARY KEY AUTOINCREMENT, job_id INTEGER NOT NULL REFERENCES jobs(id), score REAL NOT NULL, reasons TEXT, matched_at DATETIME DEFAULT CURRENT_TIMESTAMP );字段设计有两个重点。一是 jobs.source_id 设置为唯一索引这是去重的基础同一个岗位无论抓取多少次只要 source_id 不变就会因唯一约束插入失败省掉了应用层判断。二是 skills 这类多值字段用 JSON 字符串存储而不是拆关联表。对单机个人工具来说这种半结构化方式写入简单、读取方便等岗位规模到几万条再考虑规范化也不迟。3.4 第一次启动日志里藏着哪些关键信息环境配好、表结构建好之后第一次启动 get_jobs 值得认真看几眼日志。我的启动日志做了分级和模块前缀大致长这样[2025-01-15 09:00:00] [INFO ] [config] 配置加载完成共 12 个有效字段 [2025-01-15 09:00:01] [INFO ] [database] 数据表检查完毕jobs0 parsed_jds0 profile0 [2025-01-15 09:00:02] [INFO ] [collector] 开始采集目标源public_feed [2025-01-15 09:00:20] [INFO ] [collector] 本批获取岗位 42 条新增 38 条去重 4 条 [2025-01-15 09:00:21] [INFO ] [parser] 开始解析新增岗位batch38 [2025-01-15 09:00:43] [INFO ] [parser] 解析成功 36 条失败 2 条 [2025-01-15 09:01:00] [INFO ] [matcher] 匹配完成最高分 87平均分 43 [2025-01-15 09:01:02] [INFO ] [notifier] 已推送通知top5我检查启动状态时一般只看三个地方配置是否加载成功、采集新增与去重的比例、解析失败数量。配置字段缺失第一条就会失败去重比例长期过高说明数据源没真正更新解析失败率超过 5%基本可以断定 JD 文本格式变了或者模型返回不稳定。把这些指标打出来等于给每个环节装了仪表盘出问题时能很快定位到具体模块。4. 三大核心模块的搭建过程与实现思路4.1 职位采集器频率控制与去重策略采集器职责是拿原始岗位数据。以公开接口为例核心逻辑可以浓缩成下面这段代码import requests import time class PublicFeedCollector: def __init__(self, feed_url: str, interval: int 60): self.feed_url feed_url self.interval interval def fetch_batch(self) - list[dict]: resp requests.get(self.feed_url, timeout10) resp.raise_for_status() return resp.json().get(positions, []) def deduplicate(self, raw_jobs: list[dict], existing_ids: set[str]) - list[dict]: result [] for item in raw_jobs: source_id str(item.get(id, )) if source_id and source_id not in existing_ids: result.append(item) return result def run_once(self, existing_ids: set[str]) - list[dict]: raw self.fetch_batch() new_jobs self.deduplicate(raw, existing_ids) for item in new_jobs: # 输出标准化的岗位原始对象 yield { source: public_feed, source_id: item[id], title: item[title], company: item.get(company, ), raw_text: item.get(description, ), url: item.get(url, ), published_at: item.get(created_time), } time.sleep(0.5) # 单条间隔避免请求过快这段代码里有三个细节值得展开。第一是生成器写法采集是流式过程不需要把全部岗位一次性堆在内存里可以边抓取边吐给下游。第二是 existing_ids 集合由数据库已有 source_id 查询而来运行前加载一次即可。第三是 time.sleep这是最基本的礼貌性限速配合数据源要求的调用频率把本地请求间隔设成源限制的一半甚至更低能在稳定性和友好性之间取得平衡。考虑到采集任务会反复执行我在真实项目里还加了一层异常兜底单次请求失败时记日志并跳过该条不中断整批采集连续失败超过五次才触发提醒避免上游接口短暂抖动导致通知轰炸。4.2 JD 解析器用结构化提示词把岗位画像抽出来拿到原始 JD 之后下一步是让大模型把它解析成结构化字段。这是 get_jobs 里最依赖大模型的一环也是提示词设计最讲究的部分。我用的提示词模板大致如下你是一名资深招聘分析师。请阅读下面的职位描述提取关键信息并严格按 JSON 格式输出。 输出格式要求 { title: 职位名称, skills: [技能1, 技能2], years_min: 3, years_max: 5, education: 本科, salary_min: 20000, salary_max: 35000, advantages: [弹性工作, 六险一金], summary: 不超过50字的职位摘要 } 规则 1. 所有字段必须存在无法判断的字段用 null 或空数组 2. 不允许输出 JSON 以外的任何文字 3. 薪资单位统一为元/月 4. 年限范围若未写明根据职位描述推断 职位描述 {raw_text}这几个设计原则是我后来才真正体会到的。第一所有字段必须存在这条硬性规则直接提高了数据完整率大模型在宽松指令下会自作主张省略字段。第二不允许输出 JSON 以外的任何文字是为了让后续 JSON 解析一次成功。第三把任务目标说清楚而不是丢一句帮我总结一下输出质量差别非常大。调用模型的部分我抽象成通用解析函数方便统一处理重试逻辑import json from openai import OpenAI def parse_jd(raw_text: str, llm_client: OpenAI, model: str, prompt_template: str): messages [ {role: system, content: 你是一个严格的 JSON 输出助手。}, {role: user, content: prompt_template.format(raw_textraw_text[:3000])}, ] resp llm_client.chat.completions.create( modelmodel, messagesmessages, temperature0.1, response_format{type: json_object}, ) content resp.choices[0].message.content try: return json.loads(content) except json.JSONDecodeError: # 第一次解析失败定位花括号范围再试一次 start content.find({) end content.rfind(}) 1 return json.loads(content[start:end])这段代码里 raw_text[:3000] 是个很实用的细节。很多 JD 文本很长真正有用的信息集中在前半部分截断既省了 token也防止模型被末尾大段公司介绍干扰。开启 JSON 模式后大多数返回是干净的但还是要做兜底解析避免整个流水线因为一次异常中断。如果二次解析仍然失败就把原始内容存到一张失败表里供后续重试。4.3 匹配推荐器简历向量化与相似度计算匹配模块目标很直接给每条新岗位算出 0 到 100 的分数并给出推荐理由。我没有把它做成简单关键词命中而是把岗位画像和简历画像分别向量化用余弦相似度作为分数基础再叠加上硬性条件过滤。代码核心部分如下import numpy as np def cosine_similarity(vec_a: list[float], vec_b: list[float]) - float: a, b np.array(vec_a), np.array(vec_b) if np.linalg.norm(a) 0 or np.linalg.norm(b) 0: return 0.0 return float(np.dot(a, b) / (np.linalg.norm(a) * np.linalg.norm(b))) def score_job(profile_vec, job_vec, job: dict, profile: dict) - dict: base cosine_similarity(profile_vec, job_vec) # 硬性条件过滤学历、最低年限 if job.get(education) 硕士 and profile.get(education_ok) is False: return {pass: False, reason: 学历不符合要求} if job.get(years_min) and profile.get(years, 0) job[years_min]: return {pass: False, reason: 工作年限不足} # 综合分数向量相似度 70% 技能重叠率 30% job_skills set(job.get(skills, [])) profile_skills set(profile.get(skills, [])) overlap len(profile_skills job_skills) / max(len(job_skills), 1) score round(base * 70 overlap * 30, 2) return {pass: True, score: score}这个模块里最重要的决定是区分硬性条件和软性分数。硬性条件直接一票否决比如学历门槛、明确标出的最低工作年限软性分数用相似度和技能重叠率加权允许在职位描述模糊时给出相对合理排名。实际体验中硬过滤加软排序比单纯看相似度准确得多因为它先解决合不合适的边界再解决哪个更合适的排序。简历画像本身也是结构化的我会定期手动更新 profile 表里的技能列表、项目关键词和求职偏好。不建议把整份简历全文丢给模型生成向量简历里项目描述太杂向量会被非核心信息稀释。更有效的做法是只对技能标签 项目简称 求职方向这些精简字段做向量化让画像更聚焦。5. 实测阶段踩过的坑和完整排查链路5.1 坑一Python 新版本与依赖库的兼容问题现象描述创建虚拟环境后装依赖pip install 过程中某个数据处理库从源码编译报了一长串 error: command gcc failed后面还跟着 No matching distribution found。这是新版 Python 用户最熟悉的噩梦。完整排查链路我先看报错里第一个红字确认是编译阶段失败接着翻该库官方文档的版本支持矩阵发现它对新版本 Python 只支持到特定小版本。我没有浪费时间折腾编译参数而是换方案——用版本管理工具装好合适的 Python 版本重新创建虚拟环境重装依赖后一切恢复正常前后不到半小时。这里的心得是遇到编译类错误先确认版本兼容矩阵而不是和编译工具链较劲。个人项目环境配置永远选依赖支持最成熟的 Python 版本而不是最新版本。get_jobs 最终固定在 3.11后续再没有出现依赖层面的问题。这条经验同样适用其他语言生态新版本发布初期第三方库的适配往往有滞后生产项目踩成熟版本是性价比最高的选择。5.2 坑二模型返回的 JSON 时好时坏现象描述运行 JD 解析模块时偶尔出现 JSON 解析异常错误信息指向某个 Unexpected character。我最初以为是提示词不够清楚反复调整措辞可问题依旧随机出现。完整排查链路我把异常日志里的原始返回内容完整打印出来仔细对比后发现失败可以归成三类一是在 JSON 前后多了几句解释性的话二是字段名被模型改成了带空格的形式三是末尾多了一个逗号。把这三类和温度参数一对照我意识到根因是大模型生成时的随机性导致格式漂移不是提示词单方面能完全规避的。解决方案是组合拳开启模型的 JSON 输出模式把 temperature 从默认值降到 0.1再加一个二次清洗函数先用字符串定位首尾花括号再做解析。如果清洗后仍失败就完整重试一次。三个改动叠加之后解析失败率从 5% 左右降到千分之一以下接近可忽略。这个坑也说明与大模型打交道永远要假设输出可能不符合约定解析侧必须留后手。5.3 坑三采集频率过高触发限流现象描述跑了几天后采集模块突然连续报 HTTP 429 错误而之前一直是 200。我看日志发现某段时间请求间隔已经小到不足 0.2 秒在我自己的降频逻辑生效之前已经踩到数据源的访问上限。完整排查链路回溯日志后我发现根源不是采集循环本身而是某个批次岗位数量特别大循环内 sleep 固定值导致短时间集中发起了大量请求。同时我注意到响应头里有限流相关标记字段说明接口调用是有明确监管的。问题本质上是我把单条间隔写成了常量没有随批次规模做自适应调整。修复方案分两步把固定间隔改成随机间隔范围 1 到 3 秒模拟人工浏览节奏加入指数退避重试遇到 429 时先等待上一次间隔的两倍再继续下一轮。修改后连续跑了整整两周没有再出现限流。这个坑提醒我任何涉及外部接口的程序第一版就必须内置退避和随机化间隔不要等问题出现再补救。5.4 坑四token 预算失控现象描述运行第二周查看大模型调用账单发现实际消耗比预估高了一倍多。逐笔核对之后问题出在解析重试和调试调用上。完整排查链路我的第一版解析函数没有限制上下文长度整段 JD 文本全部塞给模型遇到长 JD 一次调用就消耗大量 token而解析失败后的重试又放大了消耗。更隐蔽的是我在本地调试期间反复运行脚本每次调试失败都是一次真实计费调用。这两项叠加账单自然难看。控制方案做了三个解析前统一截断原文到前 3000 字符为每条岗位维护解析状态已成功解析的不再重复调用调试模式单独用一个便宜开关避免交互调试时走完整流水线。改完之后月度消耗降到原来的三分之一。这个数字很直观地说明token 优化不是锦上添花而是长期运行的基础能力。6. 一些运行经验与后续扩展方向get_jobs 在我的机器上连续跑了快两个月。说实话它没有直接帮我拿到 offer但它确实让找工作这件事重新变得有掌控感。每天早上打开通知看到的是五条经过解析和打分的岗位推荐每条推荐理由都写在明面上——技能重合度高、年限匹配、薪酬在期望区间内。合不合适一眼就能判断不需要再逐个点开原始 JD 人肉确认。运行经验方面我总结了几条实实在在的体会。第一定时任务直接用系统自带调度器比在程序里内置定时循环更稳。我用周期任务每两小时跑一次采集加匹配失败时看日志就能定位也不用担心程序常驻内存带来的各种小问题。第二数据库备份就一条命令我每周把 SQLite 文件复制到备份目录出问题随时回滚。第三通知渠道选了邮件加消息推送双通道一个用于提醒一个用于存档。选通知渠道的原则是稳定、免费、可控不为花哨引入额外依赖。后续扩展我列了几个正在做的方向。一是生成定制化求职信草稿拿到岗位画像后让模型结合简历画像写一版申请信开头人能直接改着用。二是岗位趋势分析利用历史解析数据统计热门技能词变化判断该往哪个方向充实简历。三是面试题预测对匹配分数高的岗位让模型出几道高频面试题和回答思路。这些方向本质上都是对已有数据的复用不需要改架构只需要加新的输出模块。最后说一点个人体会。写 get_jobs 最大的收获不是代码跑通而是学会把一个模糊诉求拆成有边界的模块再逐个击破。环境配置那几天确实烦人但回头看它恰恰是整个项目里收益最高的一段时间因为所有后续调试都建立在一个干净、可控的基础上。如果你也想做类似的东西我的建议很简单先跑通最小闭环哪怕第一版只处理十条岗位数据然后再慢慢加功能。工具是给自己用的它不需要完美只需要每天准时出现替你省掉那半小时的低效劳动。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑