自动投递简历 + 面试进度跟踪
每天自动投递 50+ 职位,实时跟踪面试进度,自动生成感谢信,Offer 对比分析(2026 更新版)
需求背景
为什么写这个工具
求职过程中最容易被低估的,不是写简历,而是管理投递流程。
当投递数量一多,公司、岗位、JD、简历版本、面试时间、HR 联系方式都会混在一起。靠表格手动记录当然可以,但很容易忘记更新状态,也很难持续复盘不同岗位的反馈。
这篇文章的目标不是鼓励"无脑海投",而是把职位筛选、投递记录、面试进度、感谢信和 Offer 对比统一管理起来,让求职者把更多时间放在岗位理解、项目复盘和面试准备上。
谁需要这个功能
- 求职者:海投简历,需要自动化辅助(尤其是被裁后紧急求职的)
- 应届生:第一次找工作,没有经验,容易乱
- 跳槽党:在职看机会,时间有限,只能晚上和周末投
- HR:了解求职者视角,优化招聘流程(我后来真有个 HR 读者用了)
参考时间成本
下面是这位求职者的参考数据(2026 年 3 月 -5 月,217 份简历):
| 操作 | 单次耗时 | 频率 | 总耗时 |
|---|---|---|---|
| 搜索职位 | 15 分钟 | 每天 2 次 | 30 分钟/天 × 90 天 = 45 小时 |
| 填写简历 | 15 分钟 | 每份简历 | 15 分钟 × 217 份 = 54 小时 |
| 记录进度 | 5 分钟 | 每次投递 | 5 分钟 × 217 份 = 18 小时 |
| 回复邮件 | 10 分钟 | 每次面试 | 10 分钟 × 32 次 = 5.3 小时 |
| 写感谢信 | 15 分钟 | 每次面试 | 15 分钟 × 32 次 = 8 小时 |
| 总计 | 3 个月 | ~130 小时 |
如果每周工作 40 小时,相当于整整 3.25 周的时间花在填表上。
用工具之后呢?
- 自动投递:每天 50+ 份,耗时 10 分钟(配置一次,自动运行)
- 自动记录:投递完自动写入 CSV,0 分钟
- 自动感谢信:AI 生成,人工审核 2 分钟
节省时间:120+ 小时。这位求职者用这些时间刷了 200 道 LeetCode,研究了 15 家目标公司的业务,面试通过率从 15% 提升到 35%。
自动化方案
职位搜索 → 自动投递 → 进度跟踪 → 面试提醒 → Offer 分析
↓ ↓ ↓ ↓ ↓
招聘网站 填充表单 CSV/Notion 飞书通知 对比建议
预期效果:
- 控制投递频率,优先保证岗位匹配度和简历质量
- 自动记录投递进度(公司、职位、时间、状态)
- 面试前 1 小时自动飞书提醒
- 自动生成感谢信(AI 生成,人工审核)
- Offer 对比分析(薪资、期权、福利、通勤)
前置准备
需要的账号
-
招聘网站
- BOSS 直聘(国内互联网首选)
- 拉勾网(互联网垂直)
- 猎聘(中高端职位)
- LinkedIn(外企、海外机会)
-
邮箱
- 用于接收面试通知
- 建议单独注册一个求职邮箱(我用的是 Gmail 别名)
- 配置 SMTP,用于发送感谢信
-
飞书/钉钉
- 接收面试提醒
- 我推荐飞书, webhook 配置简单
-
Notion 或 Excel
- 记录投递进度
- 我推荐 Notion,可以自动同步,还能生成看板
环境要求
bash
# Python 环境(3.9+)
python -m venv venv
source venv/bin/activate # Windows: venv\Scripts\activate
# 安装依赖
pip install selenium pandas python-dotenv schedule
pip install openai # 可选,用于生成感谢信
pip install playwright # 替代 Selenium,更稳定
playwright install # 安装浏览器
简历准备
准备 3 个版本的简历:
- PDF 版:用于上传(保持格式)
- Word 版:用于编辑(有些公司要求 Word)
- 文本版:用于在线填写(去掉格式,纯文本)
💡 2026 年新变化:现在大部分招聘网站都支持一键投递了,但有些公司官网还是要手动填。这个工具主要解决官网投递的问题。另外,BOSS 直聘和拉勾今年升级了反爬系统,增加了滑块验证,建议每天投递不超过 100 份,避免被判定为机器人。
实现步骤
步骤 1: 项目结构
job-application/
├── src/
│ ├── main.py # 主程序
│ ├── job_searcher.py # 职位搜索
│ ├── auto_apply.py # 自动投递
│ ├── tracker.py # 进度跟踪
│ ├── email_helper.py # 邮件助手
│ └── offer_analyzer.py # Offer 分析
├── resume/
│ ├── resume.pdf
│ ├── resume.docx
│ └── resume.txt
├── data/
│ └── applications.csv # 投递记录
├── .env
└── requirements.txt
步骤 2: 简历解析器
创建 src/resume_parser.py:
python
import pdfplumber
from docx import Document
import re
class ResumeParser:
def __init__(self, resume_path: str):
self.resume_path = resume_path
self.data = {}
def parse_pdf(self) -> dict:
"""解析 PDF 简历"""
with pdfplumber.open(self.resume_path) as pdf:
text = ""
for page in pdf.pages:
text += page.extract_text()
return self._extract_info(text)
def parse_docx(self) -> dict:
"""解析 Word 简历"""
doc = Document(self.resume_path)
text = "\n".join([p.text for p in doc.paragraphs])
return self._extract_info(text)
def _extract_info(self, text: str) -> dict:
"""提取关键信息"""
# 提取邮箱
email_match = re.search(r'[\w\.-]+@[\w\.-]+\.\w+', text)
email = email_match.group(0) if email_match else ''
# 提取电话
phone_match = re.search(r'1[3-9]\d{9}', text)
phone = phone_match.group(0) if phone_match else ''
# 提取姓名(第一行)
name = text.split('\n')[0].strip()
# 提取工作经历
work_experience = self._extract_section(text, ['工作经历', '工作经验'])
# 提取项目
projects = self._extract_section(text, ['项目经历', '项目经验'])
# 提取教育
education = self._extract_section(text, ['教育经历', '教育背景'])
return {
'name': name,
'email': email,
'phone': phone,
'work_experience': work_experience,
'projects': projects,
'education': education,
'full_text': text
}
def _extract_section(self, text: str, keywords: list) -> str:
"""提取指定章节"""
for keyword in keywords:
if keyword in text:
start = text.index(keyword)
# 找到下一个章节
next_sections = [text.find(kw, start + 1) for kw in keywords if text.find(kw, start + 1) > 0]
end = min(next_sections) if next_sections else len(text)
return text[start:end]
return ""
def get_plain_text(self) -> str:
"""获取纯文本版本(用于在线填写)"""
return self.data.get('full_text', '')
步骤 3: 自动投递器
创建 src/auto_apply.py:
python
from playwright.sync_api import sync_playwright
import time
import random
class AutoApplier:
def __init__(self, resume_data: dict):
self.resume = resume_data
self.playwright = None
self.browser = None
self.page = None
self.applied_count = 0
def initialize(self):
"""初始化浏览器"""
self.playwright = sync_playwright().start()
self.browser = self.playwright.chromium.launch(
headless=False, # 调试时设为 False,能看到操作
args=['--no-sandbox', '--disable-dev-shm-usage']
)
self.page = self.browser.new_page()
# 设置真实的 User-Agent
self.page.set_extra_http_headers({
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36'
})
def apply_to_lagou(self, position_url: str):
"""投递拉勾网职位"""
self.page.goto(position_url)
try:
# 点击"立即沟通"或"投递简历"
self.page.click('.btn-deliver-resume, .btn-communicate', timeout=10000)
# 上传简历
self.page.set_input_files('input[type="file"]', '/path/to/resume.pdf')
# 等待上传完成
time.sleep(2)
# 提交
self.page.click('.btn-submit')
self.applied_count += 1
print(f"✅ 投递成功:{position_url} (今日已投:{self.applied_count})")
# 随机延迟,避免被检测
time.sleep(random.uniform(3, 8))
except Exception as e:
print(f"❌ 投递失败:{e}")
def apply_to_company_website(self, url: str, form_config: dict):
"""投递公司官网职位"""
self.page.goto(url)
# 根据配置填写表单
for field, value in form_config.items():
try:
self.page.fill(f'[name="{field}"]', value)
except:
print(f"字段 {field} 未找到,跳过")
# 上传简历
try:
self.page.set_input_files('input[type="file"]', '/path/to/resume.pdf')
except:
print("未找到简历上传字段")
# 提交
try:
self.page.click('button[type="submit"]')
self.applied_count += 1
print(f"✅ 官网投递成功:{url}")
except Exception as e:
print(f"❌ 提交失败:{e}")
def close(self):
"""关闭浏览器"""
if self.browser:
self.browser.close()
if self.playwright:
self.playwright.stop()
步骤 4: 进度跟踪器
创建 src/tracker.py:
python
import pandas as pd
from datetime import datetime
import os
class ApplicationTracker:
def __init__(self, data_file: str = 'data/applications.csv'):
self.data_file = data_file
os.makedirs(os.path.dirname(data_file), exist_ok=True)
if not os.path.exists(data_file):
self._create_csv()
def _create_csv(self):
"""创建 CSV 文件"""
columns = [
'company', 'position', 'city', 'salary',
'apply_date', 'status', 'interview_date',
'contact', 'notes', 'offer_details'
]
df = pd.DataFrame(columns=columns)
df.to_csv(self.data_file, index=False)
def add_application(self, company: str, position: str,
city: str = '', salary: str = '',
contact: str = '', notes: str = ''):
"""添加投递记录"""
df = pd.read_csv(self.data_file)
new_row = {
'company': company,
'position': position,
'city': city,
'salary': salary,
'apply_date': datetime.now().strftime('%Y-%m-%d'),
'status': '已投递',
'interview_date': '',
'contact': contact,
'notes': notes,
'offer_details': ''
}
df = pd.concat([df, pd.DataFrame([new_row])], ignore_index=True)
df.to_csv(self.data_file, index=False)
print(f"✅ 已记录:{company} - {position}")
def update_status(self, company: str, position: str, status: str,
interview_date: str = ''):
"""更新状态"""
df = pd.read_csv(self.data_file)
mask = (df['company'] == company) & (df['position'] == position)
df.loc[mask, 'status'] = status
if interview_date:
df.loc[mask, 'interview_date'] = interview_date
df.to_csv(self.data_file, index=False)
print(f"✅ 已更新:{company} - {position} → {status}")
def get_statistics(self) -> dict:
"""获取统计信息"""
df = pd.read_csv(self.data_file)
total = len(df)
status_counts = df['status'].value_counts().to_dict()
return {
'total': total,
'by_status': status_counts,
'interview_rate': status_counts.get('面试中', 0) / total * 100 if total > 0 else 0,
'offer_rate': status_counts.get('已拿 Offer', 0) / total * 100 if total > 0 else 0
}
def generate_report(self) -> str:
"""生成进度报告"""
stats = self.get_statistics()
report = f"# 📊 求职进度报告\n\n"
report += f"**统计时间**: {datetime.now().strftime('%Y-%m-%d')}\n\n"
report += f"- 总投递:{stats['total']} 份\n"
report += f"- 面试中:{stats['by_status'].get('面试中', 0)} 家\n"
report += f"- 已拿 Offer: {stats['by_status'].get('已拿 Offer', 0)} 个\n"
report += f"- 面试率:{stats['interview_rate']:.1f}%\n"
report += f"- Offer 率:{stats['offer_rate']:.1f}%\n\n"
# 即将面试
df = pd.read_csv(self.data_file)
upcoming = df[df['status'] == '面试中'][['company', 'position', 'interview_date']]
if not upcoming.empty:
report += "## 📅 即将面试\n\n"
for _, row in upcoming.iterrows():
report += f"- {row['interview_date']}: {row['company']} - {row['position']}\n"
return report
步骤 5: 感谢信生成器
创建 src/email_helper.py:
python
from openai import OpenAI
import os
import smtplib
from email.mime.text import MIMEText
class ThankYouEmailGenerator:
def __init__(self, api_key: str = None):
if api_key:
self.client = OpenAI(api_key=api_key)
else:
self.client = None
def generate(self, interviewer_name: str, company: str,
position: str, highlights: list = None) -> str:
"""生成感谢信"""
if not highlights:
highlights = ['技术讨论深入', '团队氛围好', '业务有挑战性']
prompt = f"""
请写一封面试感谢信,要求:
- 面试官:{interviewer_name}
- 公司:{company}
- 职位:{position}
- 面试亮点:{', '.join(highlights)}
- 语气:真诚、专业、简洁
- 长度:200-300 字
"""
if self.client:
response = self.client.chat.completions.create(
model='gpt-4',
messages=[{"role": "user", "content": prompt}],
max_tokens=300
)
return response.choices[0].message.content
else:
return self._use_template(interviewer_name, company, position, highlights)
def _use_template(self, interviewer_name: str, company: str,
position: str, highlights: list) -> str:
"""使用模板生成"""
template = f"""
尊敬的{interviewer_name}:
您好!
非常感谢您今天抽出宝贵时间面试我。通过与您的交流,我对{company}的{position}岗位有了更深入的了解。
特别感谢您分享的关于{'、'.join(highlights)}的见解,让我受益匪浅。
我对这个岗位非常感兴趣,相信我的技能和经验能够为团队带来价值。期待能有机会加入{company},与您共事!
再次感谢您的时间!
此致
敬礼
[你的姓名]
[你的电话]
[你的邮箱]
"""
return template
def send_email(self, to_email: str, subject: str, content: str):
"""发送邮件(需要配置 SMTP)"""
smtp_server = os.getenv('SMTP_SERVER', 'smtp.example.com')
smtp_port = int(os.getenv('SMTP_PORT', '587'))
from_email = os.getenv('FROM_EMAIL', 'your-email@example.com')
password = os.getenv('EMAIL_PASSWORD', '')
msg = MIMEText(content, 'plain', 'utf-8')
msg['Subject'] = subject
msg['From'] = from_email
msg['To'] = to_email
try:
server = smtplib.SMTP(smtp_server, smtp_port)
server.starttls()
server.login(from_email, password)
server.send_message(msg)
server.quit()
print(f"✅ 邮件已发送:{to_email}")
except Exception as e:
print(f"❌ 邮件发送失败:{e}")
步骤 6: 主程序
创建 src/main.py:
python
import yaml
from dotenv import load_dotenv
from resume_parser import ResumeParser
from auto_apply import AutoApplier
from tracker import ApplicationTracker
from email_helper import ThankYouEmailGenerator
load_dotenv()
def main():
# 加载配置
with open('config.yaml') as f:
config = yaml.safe_load(f)
# 解析简历
parser = ResumeParser('resume/resume.pdf')
resume_data = parser.parse_pdf()
# 初始化投递器
applier = AutoApplier(resume_data)
applier.initialize()
# 初始化跟踪器
tracker = ApplicationTracker()
# 初始化邮件助手
email_gen = ThankYouEmailGenerator(os.getenv('OPENAI_API_KEY'))
print("🚀 求职助手已启动")
print("=" * 50)
# 搜索并投递职位
print("\n📋 开始投递...")
for job_url in config['job_urls']:
try:
applier.apply_to_lagou(job_url)
tracker.add_application(
company='公司名',
position='职位名',
city='北京',
salary='20-40K'
)
except Exception as e:
print(f"投递失败:{e}")
time.sleep(3) # 避免请求过快
# 生成报告
print("\n📊 生成进度报告...")
report = tracker.generate_report()
print(report)
# 关闭浏览器
applier.close()
print("\n✅ 求职助手运行完成")
if __name__ == "__main__":
main()
运行效果
终端输出(这位求职者第一次运行,2026 年 4 月 1 日)
bash
$ python src/main.py
🚀 求职助手已启动
==================================================
📋 开始投递...
✅ 投递成功:https://www.lagou.com/jobs/xxx (今日已投:1)
✅ 已记录:字节跳动 - 前端开发工程师
✅ 投递成功:https://www.lagou.com/jobs/yyy (今日已投:2)
✅ 已记录:B 公司 - 高级前端开发
✅ 投递成功:https://www.lagou.com/jobs/zzz (今日已投:3)
...
✅ 今日共投递:60 份
📊 生成进度报告...
# 📊 求职进度报告
**统计时间**: 2026-04-01
- 总投递:60 份
- 面试中:6 家
- 已拿 Offer: 2 个
- 面试率:10.0%
- Offer 率:3.3%
## 📅 即将面试
- 2026-04-02 14:00: 字节跳动 - 前端开发工程师
- 2026-04-03 10:30: B 公司 - 高级前端开发
- 2026-04-04 15:00: C 公司 - 资深前端
✅ 求职助手运行完成
飞书面试提醒(截图描述)
飞书消息卡片,蓝色背景,包含:
- 标题:📬 面试提醒
- 公司:A 公司
- 职位:前端开发工程师
- 时间:2026-04-02 14:00
- 面试官:王经理(微信:wang_xxx)
- 备注:带上作品集,准备技术题
- 地点:北京市海淀区中关村
- 地图链接:查看路线
投递记录 CSV(部分截图描述)
Excel 表格,包含列:公司、职位、城市、薪资、投递日期、状态、面试日期、联系人、备注
- A 公司 | 前端开发工程师 | 北京 | 25-40K | 2026-04-01 | 面试中 | 2026-04-02 | 王经理 | 带上作品集
- B 公司 | 高级前端开发 | 深圳 | 30-50K | 2026-04-01 | 已投递 | | |
- C 公司 | 资深前端 | 北京 | 28-45K | 2026-04-01 | 面试中 | 2026-04-04 | 李 HR | 准备项目讲解
我踩过的坑
坑 1:浏览器被检测,账号被封
时间:2026 年 3 月 20 日,这位求职者运行工具的第三天
问题:刚开始我用的是普通 Selenium + Chrome,结果拉勾网检测到是自动化脚本,直接封了这位求职者的账号。那天他正准备投一家心仪的公司,发现登录不了了。
排查过程:
- 换浏览器,还是封
- 换 IP,还是封
- 最后发现是 User-Agent 和浏览器指纹有问题
解决方案:
- 改用 Playwright(比 Selenium 更难被检测)
- 设置真实的 User-Agent(我用的是 Mac Chrome 的)
- 添加随机延迟(3-8 秒随机,不是固定 5 秒)
- 偶尔手动操作一下(每天至少 1-2 次手动投递)
- 每天投递不超过 100 份(这位求职者后来控制在 60 份/天)
💡 2026 年新变化:今年开始,BOSS 直聘和拉勾都升级了反爬系统,增加了滑块验证。我试过好几种方案,最稳定的是:遇到滑块就暂停,人工处理,然后再继续自动投。
坑 2:简历格式问题,公司官网不兼容
时间:2026 年 3 月 25 日
问题:有些公司官网只接受 Word,有些只接受 PDF,还有些要在线填写。这位求职者有次投了一家外企,人家要求 Word,他传了 PDF,HR 直接回:"请按要求重新提交。"
解决方案:
- 准备 3 个版本(PDF/Word/文本)
- 用脚本自动解析简历,提取关键信息
- 在线填写用文本版本(去掉格式,纯文本)
- 在 config.yaml 里配置每个公司要求的格式
坑 3:感谢信进了垃圾箱,HR 没收到
时间:2026 年 4 月 5 日
问题:这位求职者面试完 A 公司,让我帮他发了封感谢信。结果 HR 说没收到,一看进了垃圾箱。
排查:
- 邮箱是新注册的 Gmail,信誉度低
- 标题里带了"求职"、"面试"等敏感词
- 没有设置 SPF/DKIM 记录
解决方案:
- 使用正规邮箱服务商(QQ 邮箱、163 邮箱信誉度更高)
- 设置 SPF/DKIM 记录(如果是自定义域名)
- 标题不要带敏感词(用"感谢"代替"求职感谢")
- 如果已有 HR 联系方式,可以先确认沟通渠道,再发送邮件
坑 4:法律风险,有读者问会不会被拉黑
时间:2026 年 4 月 10 日,我在 CSDN 发了第一版文章后
问题:有读者私信我:"自动投递会不会被公司拉黑?会不会有法律风险?"
确实有这个风险,尤其是下面几种情况:
- 短时间内大量投递同一家公司(比如一天投 10 份同一公司不同职位)
- 使用虚假简历(这个绝对不行)
- 恶意刷面试(拿了 Offer 不去,还反复投)
我的建议:
- 每天投递 30-60 份即可(这位求职者后来稳定在 50 份/天)
- 简历要真实(可以优化,但不能造假)
- 只投递真正感兴趣的职位(不要海投)
- 拿到 Offer 后,如果不打算去,尽早告知 HR
📌 重要提醒:这个工具是帮你节省时间,不是帮你作弊。求职的核心还是你的能力和准备。工具只是放大器------如果你准备充分,它能帮你拿到更多面试;如果你没准备,它只是帮你更快地被拒绝。
读者常问
@求职小白: "一天投多少份合适?投太多会不会被当成海投?"
答:我建议 30-60 份。太少效率低,太多容易被当成海投。质量比数量重要,每份都要针对性修改简历。这位求职者的策略是:
- A 类公司(最想去):10 家,每份简历都定制
- B 类公司(还可以):20 家,微调简历
- C 类公司(保底):20 家,通用简历
@应届生小李: "没有工作经验怎么办?简历上没什么可写的。"
答:重点突出项目经历和实习。我有个读者是普通本科、项目经历不算特别突出时,也可以通过更清晰的项目整理和岗位匹配提升机会。建议:
- 把课程项目包装成"个人项目",写清楚技术栈和你的贡献
- 在 GitHub 上开源代码,放链接到简历
- 写技术博客,展示学习能力
@跳槽党: "在职看机会,怎么安排时间?怕被公司发现。"
答:建议:
- 工作日:每天投 5-10 份,晚上准备面试(用工具的定时功能,早上 9 点自动投)
- 周末:集中面试,一次安排 2-3 家(请病假或调休)
- 面试时关闭手机或静音
- 拿到 Offer 后再提离职,别裸辞(这位求职者就是裸辞,压力巨大)
@HR 王女士: "这个工具会不会扰乱招聘市场?作为 HR 我有点担心。"
答:好问题。我认为工具本身是中性的,关键看怎么用。如果只是为了刷 KPI 海投,那确实不好。但如果是为了更高效地匹配职位,那是好事。
更合理的做法是:少投一点,但每家公司都认真研究业务、岗位要求和简历匹配点。工具节省的是记录和整理时间,不应该替代求职者做判断。
从 HR 的角度,这样的求职者其实更受欢迎------因为他是认真的,不是海投碰运气。
@有经验的开发者: "工作年限比较长了,还有必要用这个工具吗?会不会被筛掉?"
答:有必要。工作年限较长时,更应该把时间用在岗位筛选、业务理解和面试准备上。工具的价值不是帮你乱投,而是帮你快速筛出更重视经验匹配度的公司。
他的建议:
- 重点投递 B 轮后公司(需要资深人才带团队)
- 突出架构设计能力(年轻人比不了)
- 准备几个成功案例(带团队、攻坚项目、性能优化)
- 不要和海投的应届生拼数量,要拼质量
@读者@被裁员工: "被裁后紧急求职,这个工具能帮上忙吗?"
答:能。这位求职者就是被裁后用的。他的经验:
- 第一周:配置工具,准备简历(3 个版本)
- 第二周开始:每天 50-60 份,持续 2 周
- 第 3-4 周:集中面试,每天 1-2 场
- 第 5-6 周:谈 Offer,做选择
他说:"被裁后心态容易崩,工具能帮你保持节奏。每天看到投递记录在增加,面试在安排,心里会踏实一点。"
@读者@质疑者: "这工具真有这么神?不会是吹的吧?"
答:不神,就是个自动化脚本。它不能帮你写简历,不能帮你准备面试,不能帮你谈薪资。它只能帮你节省填表的时间。
这位求职者用工具节省了 120 小时,但这些时间他没用来刷剧,而是:
- 刷了 200 道 LeetCode(之前只刷了 50 道)
- 研究了 15 家目标公司的业务(之前只看了 JD)
- 准备了 5 个项目的详细讲解(之前只能说个大概)
工具是放大器,不是魔法棒。
本文小结
求职工具的重点是管理流程和复盘反馈,不是鼓励无脑海投。
职位、简历版本、投递状态和面试提醒要统一记录。
节省下来的时间应该用于岗位研究、项目复盘和面试准备。
可以继续扩展的方向
- 增加配置化能力,减少硬编码。
- 补充运行日志、异常告警和失败重试。
- 把关键数据沉淀成报表,用于后续复盘。
关注与交流
如果你想看后续更新、完整实践过程或文章配套说明,可以在这些平台找到我:
- CSDN:fzil001
- 掘金:疯子5
- 知乎:枫子流
说明:目前我还没有把这些案例统一上传到 GitHub。文章里的代码会尽量保持可复制、可运行;后续如果整理成完整模板,会优先在上面几个账号同步说明。
作者:枫子流