专利年费监控(patent-annuity-monitor)
用途
把「我名下这些专利,今年该缴哪些钱、什么时候缴、还来得及吗」这件事做成一条可以定时跑的流水线。
面向两类人,同一套流程:
- 企业 IP 负责人 — 几百到几千件在管专利,最怕漏缴导致专利权终止
- 专利代理所 — 多个客户各有一批专利,按客户分目录跑,按案卷号归档
两件事必须先懂,否则会用错
一、PatentMax 没有年费接口
PatentMax 提供的是事实:申请日、专利类型、法律状态、法律事件。
年费金额和缴费期限是本技能在本地按官方规则算出来的。
交付时必须把这两者分开说。把推算值说成「接口返回的年费」,一旦对不上,
错的不是数据,是信任。
要真正的官方缴费记录,只有两条路——用户手上的代理所台账(走 import),
或者国知局专利业务办理系统。接口推算永远是次优解,有台账就用台账。
二、滞纳期内的专利,登记簿上仍然显示「有效」
专利权要到滞纳期满(缴费期限届满后 6 个月)才终止。所以在滞纳期内的专利,
法律状态照样是「有效专利」。
只看法律状态会漏掉全部正在逾期中的专利。 必须算期限。这是本技能的存在意义之一,
也是 fee_engine 里 paid_inferred 那个状态分支的由来——过了滞纳期还显示有效的,
只能理解成已缴,但那属于推断,要提示核对。
硬约束
- 不许编数据。 检索不到的公开号,如实记进
missing_numbers并说明原因。
编一个格式正确的公开号出来,比查不到糟得多。 - 不把推断当事实。 输出里
derived是推算、data_gaps是必须人工补的窟窿,
两者在交付时要分开讲。 - 不判断减缴资格。 那是法律判断。引擎只按台账里声明的
reduction计算。 - 不报保证性结论。 不说「这些专利都没问题」。说清楚覆盖了哪些、没覆盖哪些。
- 密钥只走环境变量。 不写进任何文件、不打印、不回显。
- 改了
fee_engine.py必须跑python scripts/selftest.py。 151 项离线检查,
不联网不花钱。年费算错的代价是客户专利权终止。
命令
python scripts/annuity_monitor.py doctor # 环境/密钥/配置自检,先跑这个
python scripts/annuity_monitor.py cost --patents-file 清单.txt # 只估价,不调用
python scripts/annuity_monitor.py scan --applicant "某某股份有限公司"
python scripts/annuity_monitor.py scan --patents-file 清单.txt
python scripts/annuity_monitor.py import --ledger 已有台账.xlsx
python scripts/annuity_monitor.py plan --window 30
python scripts/annuity_monitor.py report
python scripts/annuity_monitor.py notify --days 30 --channels email,wecom
python scripts/annuity_monitor.py init-config # 生成通知渠道配置骨架
--data-dir 是全局参数,放在子命令前面。默认 annuity_data/。
每个数据目录有独立的台账、缓存、配置和发件记录,代理所按客户分开跑最清晰。
标准流程
第一步,确认环境
python scripts/annuity_monitor.py doctor
doctor 会分开报 Python 版本、密钥、网络、接口可用性、通知渠道、缓存状态。
密钥只有 scan 需要,import / plan / report / notify 全是纯本地动作,
没有密钥也能跑。
密钥失效(401 / 402 / 403 / 余额耗尽)时立即停下报告,不要转向别的数据源硬凑。
余额耗尽上游返的是 409,不是 402,脚本已经识别。
第二步,拿到台账
三条路径,按数据成熟度选,不是按方便程度选:
| 手上有 | 命令 | 准确度 |
|---|---|---|
| 代理所/国知局导出的台账 | import --ledger 台账.xlsx |
最准。已缴年度是事实 |
| 一份公开号清单 | scan --patents-file 清单.txt |
准。按号批量,一件不漏 |
| 只有企业名称 | scan --applicant "工商全称" |
够用,但申请人未做集团归一化 |
优先走 import。 已有台账里往往带着「已缴年度」,这是接口拿不到的信息。
导入支持 CSV / TSV / JSON / XLSX,中文表头自动映射(专利号、名称、申请日、
授权公告日、专利类型、已缴年度、减缴比例、案卷号、通知邮箱 等)。
识别不出专利号的行会被跳过并计数,不静默丢弃。
第三步,算账
python scripts/annuity_monitor.py plan --window 30
默认输出 Markdown,含总览表、30 天内应缴清单、需要人工补信息的清单、
以及按月支出。给客户或给领导看的时候直接贴。
加 --json 拿结构化输出,--csv 路径 导出一份可发出去的明细。
--today 2026-10-05 可以把「今天」固定住,用来复核或做演练。
第四步,出报告
python scripts/annuity_monitor.py report
生成自包含的 HTML 图表看板(内联 CSS/JS/SVG,不引任何 CDN,可以直接发出去或放进内网):
顶部一排统计卡(总量、已逾期、30 天内到期、31–90 天、今日应缴合计、数据缺口),
下面是图表网格——专利类型分布环形图、缴费风险分布环形图、法律状态分布环形图、
年费缴纳情况进度条(已缴 / 推断已缴 / 逾期 / 待缴)、未来 12 个月支出柱状图、
今日应缴金额 Top 10 横向排行,再往下是按风险分档的明细表格和本地筛选搜索框。
同一目录还会导出一份带计算结果的全量台账 CSV(UTF-8 BOM,Excel 直接打开不乱码)。
第五步,配提醒并接定时任务
python scripts/annuity_monitor.py init-config
# 改 <数据目录>/config.json,把要用的渠道 enabled 改成 true
python scripts/annuity_monitor.py doctor # 确认渠道被识别到
python scripts/annuity_monitor.py notify --days 30
渠道配置、短信网关模板、去重机制和定时任务的搭法见 references/notify-setup.md。
去重是默认行为:每封通知的键含「专利/汇总 + 缴费年度 + 提醒阶段 + 渠道 + 收件人」,
发过就跳过。定时任务一天跑几次也不会把客户邮箱塞满。--resend 强制重发。
关键参数
| 参数 | 默认 | 什么时候改 |
|---|---|---|
--batch |
40 | 每条检索式塞多少个公开号。别超过 50 |
--shard |
auto | 命中超 5000 件时按申请年份分片。none 关闭,仅在确定总量小的时候用 |
--scope |
cn | 中国专利走 cn,算年费也只需要中国专利 |
--cache-ttl |
7 | 缓存天数。法律状态变化快时配合 --refresh |
--resume |
关 | 中断后接着跑。余额耗尽导致的中断应该用它 |
--rps |
2.0 | 被限流就调到 0.5。不要调到 10 以上 |
--verify |
none | 逐件核对法律事件,每件 +¥0.20。只对重点专利开 |
--window |
30 | plan 只看未来 N 天内到期的。给 0 输出全部 |
--days |
30 | notify 提前多少天提醒,可多档如 60,30,7 |
--min-amount |
0 | 低于该金额不提醒,避免无谓打扰 |
输出物
| 文件 | 内容 |
|---|---|
<数据目录>/ledger.json |
台账主数据。人工字段(已缴年度、减缴、案卷号等)永不被 scan 覆盖 |
<数据目录>/annuity_ledger.csv |
台账导出 |
<数据目录>/annuity_ledger_enriched.csv |
带计算结果的导出,可直接发客户 |
<数据目录>/annuity_dashboard.html |
看板 |
<数据目录>/cache.json |
检索缓存,避免重复计费 |
<数据目录>/state.json |
断点 |
<数据目录>/outbox.json |
已发通知记录 |
<数据目录>/output/年费提醒.md |
file 渠道的落盘留痕 |
成本
按号批量检索是这个技能最省钱的设计:把 40 个公开号拼进一条检索式,
一次调用拿回一批,1000 件约 ¥2.5(逐号检索要 ¥100)。
| 件数 | 大致花费 |
|---|---|
| 100 | ¥0.3 |
| 1,000 | ¥2.5 |
| 5,000 | ¥12.5 |
几千件的盘点,跑之前先报一次价。 cost 子命令不调用任何接口,
scan --dry-run 只探测总量。批量细节见 references/scale-and-cost.md。
结果怎么讲
交付时至少交代四件事:
- 数据来源与覆盖范围 — 台账从哪来、接口覆盖了什么、哪些没覆盖
- 哪些是事实、哪些是推算 — 申请日和法律状态来自接口;金额、期限、滞纳金是本地算的
- 哪些必须人工核对 —
data_gaps里的每一条都要念出来,不要藏在表格里 - 口径 — 缴费期限取上一年度期满日(申请日周年日),以国知局《缴费通知书》
和专利证书载明内容为准
禁止输出「这些专利都没有年费风险」这类保证性结论。能说的是
「在已纳入台账的 N 件专利范围内,M 件在未来 30 天内需要缴费」。
不做的事
- 不算代理服务费、年登印费、印花税(不是年费,且各家报价不同)
- 不算海外年费金额(各国官费随实体规模、汇率、代理所报价浮动,留空比编一个数好)。
海外部分只算期限框架,金额需当地代理所填。fee_override支持指定金额 - 不判断年费减缴资格
- 不提供缴费通道。输出是清单和提醒,缴费走国知局专利业务办理系统或代理所
- 不覆盖商标、著作权
运行与密钥
脚本只用 Python 标准库,不需要 pip install。Python 3.7 以上都能跑。
导出的 Excel 读取(.xlsx)需要 openpyxl,没有就提示另存为 CSV,不猜。
export PATENTMAX_API_KEY="pm_live_你的密钥" # PowerShell 是 $env:PATENTMAX_API_KEY="..."
密钥在 https://api.ip930.com/features/api-platform 创建。新用户注册送体验额度,
够跑几百次检索。
pm_live_ 是生产密钥,正常都用它。pm_test_ 是沙箱密钥,检索每天 30 次且不返回真实
结果,只在验证参数时用,不要拿它跑生产盘点。
只访问一个域名 api.ip930.com(scan / doctor),其余动作不联网。
通知渠道按配置访问用户自己指定的 SMTP 服务器或 webhook 地址。
参考
references/fee-rules-cn.md— 年费标准表、期限算法、滞纳金阶梯、减缴、状态判定。
改fee_engine.py前先读这份references/data-source.md— PatentMax 能取到什么、取不到什么、A/B 本归并、
5000 件上限、字段名坑references/scale-and-cost.md— 上千件的分片、断点、缓存、成本、对账策略、
代理所多客户组织方式references/notify-setup.md— 七种渠道的配置示例、短信网关模板、去重机制、定时任务
templates/ledger_template.csv 是台账模板,templates/config.example.json 是渠道配置示例。
正常执行流程不需要读参考文档,遇到异常或要改规则时再查。
自测
python scripts/selftest.py
159 项离线检查,不联网、不花钱、不碰真实台账。覆盖日期与官费规则、
滞纳金边界、法律状态归并、A/B 本去重、清单读取、台账人工字段保护、以及从导入到看板的
整条链路。任何一项不过就不要发布这个技能。