7.4 KiB
铁路系统发票批量处理使用说明
原则
- 只使用铁路 12306 官方页面/App 完成开票。
- 本工具不保存 12306 账号密码,不绕过验证码或身份核验。
- 公司抬头、税号、接收邮箱从本地配置读取;不要写入
.env。 config.local.json已被.gitignore忽略,不要把真实公司信息写进config.example.json。
初始化
python3 scripts/invoice_tool.py init
先复制一份本地配置:
cp config.example.json config.local.json
然后把 config.local.json 里的三项改成真实值:
{
"company_title": "公司全称",
"tax_id": "统一社会信用代码",
"receiver_email": "统一收票邮箱"
}
导入开票码
把旅行社给的二维码图片或 PDF 放到:
data/input/开票码批次/
执行:
python3 scripts/invoice_tool.py import-codes
输出台账:
work/invoice_tasks.csv
如果本机没有二维码解码器,任务会进入 待补码。人工扫码后,把链接或码写入:
data/input/开票码批次/manual_codes.csv
再执行一次 import-codes。
如果这是铁路“扫码开票单”截图,二维码通常只能用 12306 App 扫。可以在
manual_codes.csv 里用 APP_SCAN 补录开票单号和代办人:
source_file,passenger,ticket_ref,code
data/input/开票码批次/ScreenShot_xxx.png,张*木,EKP37846902581249178,APP_SCAN
真实手工 POC
第一次必须用 1-3 张真实开票码在 Mac 上跑通:
- 把真实二维码图片/PDF 放进
data/input/开票码批次/。 - 执行
python3 scripts/invoice_tool.py import-codes。 - 打开
work/invoice_tasks.csv看状态:待网页开票:说明二维码可在 Mac 网页端继续,后续可做更强的网页自动化。待人工扫码/待补码:说明大概率要 12306 App 扫码,Mac 端只能做台账、收票和归档自动化。
- 手动登录 12306,完成身份核验。
- 执行
python3 scripts/invoice_tool.py rpa-plan,打开output/rpa_helper.html。 - 用辅助页逐条打开官方页面,填写统一公司抬头、税号、邮箱并提交。
- 收到邮件后,把
.eml放入data/mail/,或把附件放入data/attachments/。 - 执行归集和汇总命令,检查
output/发票汇总.xlsx。
Android 自动填写身份证后 8 位
适用场景:12306 App 扫码后,页面显示脱敏姓名(如 张*岩),要求输入身份证后 8 位验证码。
本地 Web UI
启动本地页面:
python3 scripts/web_ui.py
打开:
http://127.0.0.1:8765
页面支持上传 .xlsx/.xlsm/.csv 名单、查看成功/失败/处理中/未操作统计、显示手机连接/当前 App 状态、启动手机 12306、抓取当前页队列、启动/停止批处理,并持续读取:
work/android_invoice_progress.csv
这个 CSV 是逐人处理结果表,页面里的“下载进度表”会直接下载它。
1. 导入 Excel 名单
名单里至少要有“姓名”和“身份证/证件号码”两类列名。支持 .xlsx/.xlsm/.csv:
python3 scripts/invoice_tool.py import-roster --input /path/to/名单.xlsx
输出:
work/passenger_roster.csv
先离线验证一个脱敏姓名:
python3 scripts/invoice_tool.py match-roster --masked-name '张*岩'
如果出现 ambiguous,说明同名脱敏后匹配到多人,必须人工确认。
2. 连接 Android 手机
手机开启 USB 调试后连接 Mac:
/opt/homebrew/share/android-commandlinetools/platform-tools/adb devices
先手工在 12306 App 扫码,进入要求填写身份证后 8 位的页面。
读取当前页面文字:
python3 scripts/invoice_tool.py android-dump --output work/android_page.txt
如果能看到 张*岩 这类文字,就可以自动匹配并输入身份证后 8 位:
python3 scripts/invoice_tool.py android-type-id --tap 500,1200
--tap 是输入框坐标,需要按手机页面实际位置改。也可以用按钮/输入框可访问文字:
python3 scripts/invoice_tool.py android-type-id --click-text '证件号码后8位' --contains
3. 后续点击流程
复制并修改模板:
cp templates/android_flow.example.json templates/android_flow.local.json
python3 scripts/invoice_tool.py android-run-flow --flow templates/android_flow.local.json
模板支持这些动作:
| action | 用途 |
|---|---|
click_text |
按完整文字点击 |
click_contains |
按包含文字点击 |
tap |
按坐标点击 |
input_id8_for_visible_masked_name |
从当前页面识别 张*岩 并输入身份证后 8 位 |
input_config |
输入 config.local.json 中的公司抬头、税号、邮箱 |
input_text |
输入固定文本 |
sleep |
等待 |
keyevent |
发送 Android keyevent |
真实 12306 App 页面可能不暴露全部控件文字。遇到找不到控件时,用 android-dump 看文字;如果没有文字,就改用 tap 坐标。
4. 单步状态机
当前页面已校准后,优先用单步命令。它每次只做一步动作,默认等待 10 秒,未出现目标状态再等 20 秒,仍不成功就暂停:
python3 scripts/invoice_tool.py android-invoice-step
如果当前在“发票开具成功”页,默认会点 继续开票 回列表。需要先发邮件时才加:
python3 scripts/invoice_tool.py android-invoice-step --send-email
5. 扫码列表页批处理队列
扫码开票单列表页不要用固定坐标。先抓当前可见的一页,按脱敏姓名和名单生成队列:
python3 scripts/invoice_tool.py android-build-page-queue
队列文件:
work/android_page_queue.csv
然后反复跑:
python3 scripts/invoice_tool.py android-page-step
行为:
- 当前在扫码列表页:按本页队列点击下一个可匹配人员的
开具。 - 当前在核验/发票管理/发票信息/成功页:执行普通单步状态机。
- 本页没有可处理人员:输出
page_done,不自动乱滑。
本页处理完后上滑到下一页并重建队列:
python3 scripts/invoice_tool.py android-page-next --rebuild
也可以让 android-page-step 在本页完成后自动上滑:
python3 scripts/invoice_tool.py android-page-step --auto-next
网页辅助开票
python3 scripts/invoice_tool.py rpa-plan
打开:
output/rpa_helper.html
先手动登录 12306 并完成核验,再逐条打开官方页面,复制公司抬头、税号和邮箱提交。
邮件和附件归集
如果有 .eml 邮件文件:
python3 scripts/invoice_tool.py collect-mail
如果已经把 PDF/OFD/XML 附件下载到 data/attachments/:
python3 scripts/invoice_tool.py collect-attachments
归集后的发票在:
output/invoices/
汇总和查漏
python3 scripts/invoice_tool.py export-summary
输出:
output/发票汇总.xlsx
工作簿包含:
发票汇总缺票清单合规检查
状态含义
| 状态 | 含义 |
|---|---|
待补码 |
未能自动识别二维码,需要人工扫码补录 |
待人工扫码 |
码不是网页链接,通常需要 12306 App 扫码 |
待网页开票 |
可以从辅助页打开官方页面处理 |
已收票 |
已匹配到发票附件 |