ETERNITY 价格提取 Skill
提取 ETERNITY 空运运价(OCR 图片 / 手动录入)→ 24列标准输出 → 上传 WPS。
⚠️ 铁律:仅提取用户最新提交文件,禁止复制历史数据
- 禁止查看/引用/复制任何历史脚本中的 price/data 数组
- 禁止从历史输出文件直接读取数据
- 禁止硬编码历史图片/Excel 路径作为源文件
- 每次提取必须从用户当前提交文件全新 OCR/读取
- 有就是有,没有就是没有:不得用历史数据填补缺失值
- 历史提取数据仅作规则参考
一、核心参数(全部路线共享)
| 参数 | 值 |
|------|-----|
| 起始港 | PVG(个别 HGH) |
| 来源 | ETERNITY |
| 引擎 | ocr_utils(跨平台统一 RapidOCR 封装,~/.workbuddy/skills/ocr_utils.py)+ 手动录入数据 |
| 45KG | 部分路线为空(货机直飞) |
通用提取规则
| 规则 | 说明 |
|------|------|
| 货型转换 | 平泡货/平货/散舱/托盘散货 → 1:1 |
| 航司简化 | CK257/261/263→CK, CZ313/369/3095→CZ, VN531/523→VN |
| 散托默认 | 散货/托盘(无托盘+N备注时) |
| 分泡 | 不提取分泡数据,分泡列始终留空 |
| 频次 | 频次为空时填 Daily(0727全局规则) |
| 忽略文本 | 所有「其他说明」行(ETD/ETA/机型/时刻) |
| 底部转运表 | 图片底部黄色『转运点(X转, 限定XX转, 指定转运+N)』区块(LHR/FRA/AMS/FCO/BCN/MAD/MXP 等欧线常见)→ 提取为转运点行:跳转点=空运到达机场,转运点=卡车终点,转运费增量值(RMB/KG)=单价,转运费最低收费(/票)=Min;价格列(45/100/300/500/1000KG)全留空、货型=1:1、比重=0~9999。详见坑22 |
二、强制流程
1. 确认输入类型(OCR图片 或 手动录入Excel)
2. OCR图片型:ocr_utils.scan_to_log() 扫描 → 日志 → 对照手动录入数据
3. 手动录入型:直接读取数据表
4. 生成 24 列 DataFrame
5. 保存 → 上传 WPS
2.1 OCR 统一导入(所有平台一致)
import sys, os
sys.path.insert(0, os.path.expanduser('~/.workbuddy/skills'))
from ocr_utils import scan_image, scan_to_log, check_env
check_env() # 启动时自检,确保引擎版本一致
三、16 条路线配置表 ⚠️ 核心参考
3.1 索引表
| # | 触发词 | 价格编号 | 目的地 | 航司 | 频次 | 特殊 |
|---|--------|---------|--------|------|------|------|
| 1 | LHR | eternity_muca_lhr_001 | LHR | MU/CA | Daily | - |
| 2 | TPE | eternity_czck_tpe_001 | TPE | CZ/CK | CZ:Daily CK:D23456 | 跳转点模式 |
| 3 | BKK/SIN/HAN | eternity_ck_bkksinhan_001 | BKK,SIN,HAN | CK | SIN/HAN:D34567 BKK:D357 | 多目的地 |
| 4 | HAN(CA) | eternity_ca_han_001 | HAN | CA | D257 | 45KG全N/A |
| 5 | HKG | eternity_ck_hkg_001 | HKG | CK | 非散舱:D3467, 散舱:Daily | - |
| 6 | AMS | eternity_czckca_ams_001 | AMS | CZ/CK/CA | Daily | 多航司 |
| 7 | LAX | eternity_czckca_lax_001 | LAX | CZ/CK/CA | Daily | 多航司 |
| 8 | ORD | eternity_czckcake_ord_001 | ORD | CZ/CK/CA/KE | Daily | 4航司 |
| 9 | FRA | eternity_czckcalh_fra_001 | FRA | CZ/CK/CA/LH | Daily | 4航司 |
| 10 | JFK | eternity_caqfke_jfk_001 | JFK | CA/QF/KE | Daily | 3航司 |
| 11 | NLU | eternity_cz_nlu_001 | NLU | CZ | Daily | 单航司 |
| 12 | YYZ | eternity_czkemu_yyz_001 | YYZ | CZ/MU/KE | Daily | 3航司 |
| 13 | SGN/越南 | eternity_vn_hansgn_001 | HAN,SGN,DAD | VN | Daily | 多目的地 |
| 14 | SGN(CZ) | eternity_cz_sgn_001 | SGN | CZ | Daily | 单航司 |
| 15 | NRT/KIX | eternity_czck_nrtkix_001 | NRT,KIX | CZ/CK | CZ:Daily CK:D36/D26 | 日本双港 |
| 16 | ICN | eternity_ckcz_icn_001 | ICN | CK/CZ | Daily | 韩国 |
| 17 | DEL | eternity_cxcims_del_001 等4个 | DEL | CX/CI, VN/NH, MU, CX(HGH) | 各不同 | PVG/HGH双港 |
| 18 | BOM | eternity_cxcims_bom_001 等3个 | BOM | CX/CI, NH/MH/VN, CX(HGH) | 各不同 | PVG/HGH双港 |
| 19 | MAA | eternity_cx_maa_001 / eternity_mh_maa_001 | MAA | CX, MH | 各不同 | MH泡托/泡散 |
| 20 | BLR | eternity_cx_blr_001 | BLR | CX | D44/D67 | - |
| 21 | HYD | eternity_cx_hyd_001 | HYD | CX | D66/D77 | - |
| 22 | CMB | eternity_cx_cmb_001 | CMB | CX | D71/D34 | ⚠️平+200KG起 |
| 23 | DAC | eternity_cx_dac_001 | DAC | CX | D72 / D56 | ⚠️抛货+普货, 城市差异 |
| 24 | CZ腹舱直达/CZ直达 | eternity_cz_cz_001 | TPE,SGN,NRT,ICN | CZ | Daily | 停飞行跳过 |
| 25 | HO | eternity_ho_ho_001 | HKG,TPE,KHH,BKK,HAN,SGN,KUL,DPS,PEN,KIX,NRT,HND,NGO,SIN,SYD,MEL,ADL,BNE,PER | HO | 各不同 | 澳线中转,0713更新 |
| 26 | CK亚大线直飞 | eternity_ck_ck_001 | ICN,HKG,TPE,SIN,HAN,BKK,NRT,KIX | CK | 各不同 | 亚太直飞 |
3.2 路线详细规则
#1 LHR(MU/CA)⚠️ 0713 更新
| 项目 | 值 |
|------|-----|
| 源文件 | 用户提交 |
| 价格编号 | eternity_muca_lhr_001 |
| 生效日期 | 图片标题提取(如 2026/7/13 起 → 2026-07-13) |
| 航司 | MU/CA |
| 频次 | Daily |
| 脚本模板 | extract_eternity_muca_lhr.py |
| 价格列 | 图片仅有 +100/+300/+500/+1000,45KG 留空 |
| 货型/比重 | 1:100(0-100)、1:120(100-120)、平/泡 1:1(120-200)、1:200(200-250)、1:250(250-300)、1:300(300-400)、1:400(400-500)、1:500(500-800)、1:800(800-1000)、1:1000(1000-9999) |
| 散托类型 | 行货型含"散"→散货;含"托"→托盘;"托/散"→散货/托盘 |
| 转运点 | 图片底部黄色区块为 LHR 卡车转运点,逐行输出到转运点列,单价→转运费增量值(RMB/KG),Min→转运费最低收费(/票) |
| 全局备注 | 泡货分半泡、小货(<100kgs)+300/票、尺寸/垫板费规则写入每行 Remark;ETD/ETA/时刻忽略 |
#2 TPE(CZ/CK)⚠️ 跳转点
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 2026-04-22 | | 航司频次 | CZ→Daily, CK→D23456 | | 货型 | 托盘→1:1, 散货→1:1, 1:300/1:400/1:500保留 | | 备注 | CZ→泡货:1:120, CK→泡货:1:120 | | 跳转点 | 中转地 → 跳转点列 |
#3 BKK/SIN/HAN(CK)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 图片标题提取(如"2026年5月18日起"→2026-05-18) | | 目的地 | SIN, BKK, HAN(三港各一行) | | 频次 | SIN:D34567, BKK:D357, HAN:D34567 | | 航司简化 | CK283/275/284/278→CK | | 货型 | 托盘/散货→1:1 |
#4 HAN(CA)⚠️ 45KG全N/A
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 图片标题提取(如"2026年5月25日起"→2026-05-25) | | 频次 | D257(货机) | | 货型 | 托盘/散货→1:1;图片出现 1:200 则保留为 1:200 | | 45KG | 全部为 N/A(货机直飞) | | 比重 | 按图片实际价格行输出,不得链式补展开;0615 批次仅 2 行:1:1(0→200)、1:200(200→9999) |
#5 HKG(CK)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 图片标题提取(如"2026年5月25日起"→2026-05-25) | | 频次 | 非散舱:D3467, 散舱:Daily(逐行区分,不要统一为Daily) | | 货型 | 平货→1:1, 散舱→1:1, 1:200/1:300保留 |
#6 AMS(CZ/CK/CA)
| 项目 | 值 |
|------|-----|
| 源文件 | 用户提交 |
| 生效日期 | 2026-04-22 |
| 航司 | CZ/CK/CA(共享同一价格表) |
| 货型 | 1:100单询行不提取;1:100以上散/托双行提取为 >100;1:200-1:1000 保留 |
#7 LAX(CZ/CK/CA)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 从图片标题提取;0615 批次为 2026-06-17 | | 航司 | CZ/CK/CA | | 45KG | 无 45KG 独立报价,留空 | | 散托增量 | 逐行读“其他说明”:托盘+2 → 散货/增量2;托散同价 → 散货/托盘/增量空 |
#8 ORD(CZ/CK/CA/KE)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 从图片标题提取;0615 批次为 2026-06-18 | | 航司 | CZ/CK/CA/KE(4航司) | | 45KG/300KG | 图片仅有 +100/+500/+1000,45KG 和 300KG 留空 | | 散托增量 | 逐行读“其他说明”:托盘+2 → 散货/增量2;托散同价 → 散货/托盘/增量空 |
#9 FRA(CZ/CK/CA/LH)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 2026-04-22 | | 航司 | CZ/CK/CA/LH(4航司) |
#10 JFK(CA/QF/KE)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 从图片标题提取;0615 批次为 2026-06-15 | | 航司 | CA/QF/KE(3航司) | | 45KG | 图片仅有 +100/+300/+500/+1000,45KG 留空 | | 货型 | 1:80-1:400 散/托双行;1:500/1:800/1:1000 托散同价 | | 频次 | 取说明中最高频次,0615 批次按 CA DAILY 输出 Daily |
#11 NLU(CZ)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 2026-04-22 | | 航司 | CZ(单航司) | | 货型 | 平货→1:1, 1:250/1:300/1:500保留 |
#12 YYZ(CZ/MU/KE)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 从图片标题提取;0615 批次为 2026-06-18 | | 航司 | CZ/MU/KE(3航司) | | 45KG | 图片有 +45KG 列,需逐行填写;0615 批次均为 65 | | 300KG | 图片无 +300KG 列,300KG 留空 | | 散托增量 | 逐行读“其他说明”:托盘+2 → 散货/增量2;托散同价 → 散货/托盘/增量空 |
#13 HAN/SGN/DAD(VN)⚠️ 0713 更新
| 项目 | 值 |
|------|-----|
| 源文件 | 用户提交 |
| 生效日期 | 从图片标题提取;0615 批次为 2026-06-15,0713 批次为 2026-07-13 |
| 目的地 | 按图片逐行输出;目的港为空格或斜杠拼接时统一改为英文逗号拼接;0713 批次包含 XPS,SGN,HAN、HAN、SGN、DAD、VTE、KTI,CGK,MNL、BKK,SIN,KUL、SYD、MEL、PER、BOM、DEL、BLR,HYD、JNB |
| 航司 | VN(VN531/523→VN) |
| 货型/比重 | 合并货型"散/托同价 不分泡"标准化为货型 1:1;比重统一 0-9999 |
| 散托类型 | 散货/托盘 |
| 跳转点 | 图片左侧标注 HAN/SGN中转 的区块,跳转点填 HAN,SGN;直达 HAN/SGN/DAD/VTE/KTI/CGK/MNL/BKK/SIN/KUL 行留空 |
| 价格列 | 图片有 +45/+100/+300/+500/+1000/+2000;标准表只填 45/100/300/500/1000KG,+2000KG 忽略;空白格留空 |
| 频次 | 天天窄体/天天宽体/二程天天宽→Daily;其他 二程窄体/二程宽体/二程1宽 等保留在 Remark,频次留空 |
| 特殊备注 | 暂时封舱 不是停飞,价格保留,备注中体现该状态 |
#14 SGN(CZ)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 2026-04-22 | | 航司 | CZ(单航司) |
#15 NRT/KIX(CZ/CK)⚠️ 日本双港
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 2026-05-11 | | 目的地 | NRT, KIX | | 航司 | CZ, CK(CZ8309-NRT / CK241-NRT / CK247-KIX) | | 频次 | NRT-CZ:Daily, NRT-CK:D36, KIX-CK:D26 | | 货型 | 平散/托→1:1, 1:200/1:300/1:400保留 |
#16 ICN(CK/CZ)
| 项目 | 值 | |------|-----| | 源文件 | 用户提交 | | 生效日期 | 2026-04-22 | | 航司 | CK/CZ(2航司) | | 比重起始 | CK=1000, CZ=300 |
#24 CZ腹舱直达(CZ)
| 项目 | 值 |
|------|-----|
| 源文件 | 用户提交 |
| 生效日期 | 从图片标题提取;0615 批次为 2026-06-15 |
| 价格编号 | eternity_cz_cz_001 |
| 航司 | CZ |
| 目的地 | TPE、SGN、NRT、ICN;目的港如有空格/斜杠拼接统一转英文逗号 |
| 货型/比重 | TPE: 1:1(0-300), 1:300(300-400), 1:400(400-9999);SGN/NRT: 散货→1:1(0-9999);ICN: 1:1(0-250), 1:250(250-9999) |
| 价格列 | 图片有 +45/+100/+300/+500/+1000/+2000;标准表只填 45/100/300/500/1000KG,+2000KG 忽略 |
| 停飞 | 频次/说明为“停飞”的行整行跳过,不生成记录 |
#25 HO(HO)⚠️ 多目的地 + 澳线中转
| 项目 | 值 |
|------|-----|
| 源文件 | 用户提交 |
| 生效日期 | 从图片标题提取;0615 批次为 2026-06-15,0713 批次为 2026-07-13 |
| 价格编号 | eternity_ho_ho_001 |
| 航司 | HO |
| 目的地 | 按图片逐行输出;目的港为空格或斜杠拼接时统一转英文逗号 |
| 直达目的地 | HKG、TPE、KHH、BKK、HAN、SGN、KUL、DPS、PEN、KIX、NRT、HND、NGO、SIN、SYD、MEL |
| 中转目的地 | ADL、BNE、PER;图片左侧标注 PVG SYD/MEL中转 接第二天卡车,跳转点填 SYD,MEL,Remark 填 PVG SYD/MEL中转 接第二天卡车 |
| 货型/比重 | 单条 散货 行→1:1(0-9999);托盘/散货 + 比重行按图片实际输出(禁止补展开) |
| 多比重示例 | TPE: 1:1(0-300)、1:300(300-9999);KIX/NRT: 1:1(0-300)、1:300(300-500)、1:500(500-1000)、1:1000(1000-9999);SIN: 1:1(0-300)、1:300(300-500)、1:500(500-1000)、1:1000(1000-9999);SYD/MEL/ADL/BNE/PER: 1:1(0-300)、1:300(300-500)、1:500(500-9999) |
| 价格列 | 图片有 +45/+100/+300/+500/+1000/+2000;标准表只填 45/100/300/500/1000KG,+2000KG 忽略;- 留空 |
| 散托类型 | 行货型为 散货 → 散货;行货型为 托盘/散货 → 散货/托盘;无 托盘+N 备注则增量空 |
| 特殊备注 | 0713 批次 SYD/MEL 含 平散-2,整入 Remark;BKK/HAN 含 暂时不接 不跳过,仅记入 Remark |
| 频次 | 天天→Daily;XXX航班→DXXX;无明确数字时留空(如中转澳线) |
#26 CK亚大线直飞(CK)
| 项目 | 值 |
|------|-----|
| 源文件 | 用户提交 |
| 生效日期 | 从图片标题提取;0615 批次标题为 2026-06-08 起 |
| 价格编号 | eternity_ck_ck_001 |
| 航司 | CK(CK257/263/261/283/284/278/275/241/247 均简化为 CK) |
| 目的地 | ICN、HKG、TPE、SIN、HAN、BKK、NRT、KIX;目的港如有空格/斜杠拼接统一转英文逗号 |
| 货型/比重 | 托盘/散货、散舱(客机)均按图片实际行输出为 1:1(0-9999),不链式补行 |
| 频次 | ICN=D367;HKG托盘/散货=D23467;HKG散舱=Daily;TPE=D23456;SIN/HAN=D34567;BKK=D357;NRT=D36;KIX=D26 |
| 备注 | TPE 的 周六+1/KG、HKG散舱限制、HAN经停不卸货可保留;ETD/ETA/机型等航班时刻默认忽略 |
| 价格列 | 图片有 +45/+100/+300/+500/+1000;全部按图片数字原样保留小数 |
四、OCR 提取模式(部分路线)
部分路线通过 OCR 日志辅助,但数据实际为手动录入。
# 标准 OCR 日志记录
ocr = RapidOCR()
ocr_result, _ = ocr(IMAGE_PATH)
for item in ocr_result:
box, text = item[0], item[1]
y, x = int(box[0][1]), min(box[0][0], box[1][0])
# 日志记录,供人工校正
五、数据录入模式
多数 ETERNITY 脚本使用硬编码手动录入:
# 模式1:纯硬编码(如 AMS)
data = [
('1:100', '', '', '', 0, 100, '散货', '单询'),
('1:200', 44, 44, 44, 200, 249, '散货', ''),
...
]
# 模式2:从手动录入Excel读取(如 VN HAN/SGN/DAD)
df_raw = pd.read_excel(INPUT_FILE)
# 列名映射 + 标准24列输出
六、货型与比重规则
货型转换表
| 原始 | 输出 |
|------|------|
| 平泡货 / 平货 | 1:1 |
| 散舱 / 托盘散货 | 1:1 |
| 托盘(无备注+N) | 1:1 |
| 1:200 / 1:300 等 | 保留 |
| 散货/托盘后缀 | 去掉,仅保留比重 |
比重起始规则(1:1 档)
| 路线 | 1:1 开始 | 1:1 结束 | |------|---------|---------| | ICN CK | 0 | 1000 | | ICN CZ | 0 | 300 | | HKG | 0 | 300 | | HAN(CA) | 0 | 500 | | BKK/SIN | 0 | 9999 |
七、散托类型判断
与全局规则一致:
- 备注含
+N→ 散货,增量=N - 无增量但货型含"托" → 托盘
- 无增量含"散" → 散货
- 默认 → 散货/托盘
八、常见坑
坑1:CA-HAN 45KG 全 N/A
货机直飞无 45KG 报价,不能填 0 或 fallback。
坑2:TPE 跳转点
中转地必须填入跳转点列而非转运点列。
坑3:航司简化
OCR 可能读到 CK257/CZ313 等含数字的航司,必须简化。
坑4:BKK/SIN/HAN 多港一行
三个目的地共享同一价格表,每行产出 3 条记录。
坑5:NRT/KIX 不同频次
CZ8309:Daily, CK241:D36, CK247:D26,不能统一。
坑7:单询行不提取(0525新增,0615补充)
重量段价格全为非数字(如"单询")的行跳过不提取。 仅提取所有价格列为有效数字的行。
0615 AMS 教训:图片第一行 1:100以下 单询 靠45 50 表示价格为空,不能生成记录;其中 靠45 50 是说明文字,不是 45KG=45/50 报价,也不能写入 45KG 列。
坑8:散托增量从备注提取(0525新增)
备注含 托盘+X元/KG 或 托盘+X → 散货,增量=X。
例如:托盘+1元/KG → 散托类型=散货,散托增量=1。
无托盘声明 → 散货/托盘,增量空。
坑9:OCR 价格数字识别错误(0525新增)
OCR 可能将 41→21 看错。每行价格必须人工对照图片逐行核实,不能信任自动 OCR 结果。
坑10:合并单元格托散同价被误继承 + 覆盖范围误判(0525新增,0601补充)
当「托散同价」在合并单元格中垂直居中时,合并范围内的空行会错误继承上行的「托盘+N」备注。 规则:遇到合并单元格备注,合并范围内所有行共享同一备注和散托类型,不能逐行独立继承。
⚠️ 0601 补充(NLU 线路):OCR 可能将合并单元格首行(如 1:400)的「托散同价」错误识别为「托盘+2元/kg」, 导致合并覆盖范围起止行误判。必须人工对照原始图片确认合并单元格的实际覆盖起止行。
坑11:逐行核实备注,禁止批量推断(0525新增)
同一价格表中不同货型可能有不同增量值(如 1:167 托盘+4 但左右行是+2)。 规则:每行备注必须逐行人工核对,不能批量假定相邻行相同。散托增量不可跨行继承。
坑12:频次从「其他说明」合并取最大值(0525新增)
多航司表格底部「其他说明」中列出各航司频次(CA DAILY, QF D3/7, KE D1-7), 取所有航司中频次最高者作为统一输出(如 KE D1-7 → Daily)。
坑13:航班号不放跳转点(0525新增)
跳转点列仅用于中转地三字码(如 TPE 的跳转点模式)。 航班号(CZ8309/CK241 等)不属于跳转点,应放入备注列或忽略。
坑21:HO 航线「暂时不接」与「平散-2」处理(0713新增)
症状:HO 图片中 BKK/HAN 行标注 天天暂时不接,SYD/MEL 行标注 平散-2。
规则:
暂时不接不是停飞,价格仍然存在,整行保留,备注中体现该状态。平散-2是无处放置的货型/调整说明,整入 Remark 列。- HO 澳线中转(ADL/BNE/PER)Remark 统一为
PVG SYD/MEL中转 接第二天卡车,跳转点=SYD,MEL;中转行无航班数字,频次留空。
坑22:底部黄色卡车转运表格 → 转运点行(LHR / FRA / AMS / FCO 等欧线常见,0803更新)⚠️
症状:欧线价格表底部有黄色区块,列标题通常是 转运点(XXX转…) / 单价(+100kgs)/KG / Min,
每行一个卡车转运目的地(多城市可能用 / 拼接,如 MAN/BHX/EMA)。LHR 已知,FRA/AMS/FCO 等同样适用。
字段映射规则(0803 已落地,参 extract_muca_lhr_0803.py:build_transit_records):
- ⚠️ 目的港 = 卡车转运最终目的地(如
MAN/BHX/EMA、GLA),不是空运到达机场 LHR。 与 HO 澳线模式一致(目的港=卡车终点 ADL/BNE/PER)。原因:转运到 MAN 的货物理货点在 MAN,下游"按目的港分类/报价"若算到 LHR 会失真。 - 跳转点 = 空运到达机场(如
LHR),表示货物先飞到该机场再卡车转运。 - 转运点 = 卡车转运最终目的地(与目的港同值)。
- 转运费增量值(RMB/KG) = 黄色表格「单价」数值(数字原样,如
2.60)。 - 转运费最低收费(/票) = 黄色表格「Min」数值(保留 2 位小数,如
350.00)。 - 价格列(45/100/300/500/1000KG)全部留空(这是二段费用不是主段价格)。
- 货型/开始比重/结束比重 =
1:1/0/9999(占位,转运不分段)。 - 频次/散托类型/散托增量 = 留空。
- Remark = 黄色表格顶部说明,如
转运点(LHR转,仅限MU551转,指定转运+4)。
完整代码示例:
TRANSIT = [
# (目的点, 增量值 RMB/KG, 最低收费 Min)
('MAN/BHX/EMA', 2.60, 350.00),
('GLA', 3.10, 350.00),
('LPL', 3.40, 350.00),
('ABZ', 3.70, 350.00),
('DUB', 3.90, 350.00),
('BFS/SNN/ORK', 4.40, 450.00),
]
def build_transit_records():
out = []
remark = '转运点(LHR转,仅限MU551转,指定转运+4)'
for dest, inc, min_charge in TRANSIT:
out.append({
'起始港': 'PVG', '目的港': dest, '航司': AIRLINE,
'开始比重': 0, '结束比重': 9999, '货型': '1:1',
'45KG':'', '100KG':'', '300KG':'', '500KG':'', '1000KG':'',
'散托类型':'', '频次':'', 'Remark': remark,
'跳转点': 'LHR', # 空运到达机场
'转运点': dest, # 卡车终点(同目的港)
'转运费增量值(RMB/KG)': str(inc),
'转运费最低收费(/票)': f'{min_charge:.2f}',
'备注':'', '来源':'ETERNITY',
'价格编号': PRICE_NO, '散托增量':'',
})
return out
❌ 旧错误规则(0713版,已废弃):~~目的港保持 LHR~~ —— 这是错的,会压缩 6 个转运目的地为同一行,下游按目的港统计会失真。
坑23:VN 越南线「暂时封舱」与二程频次处理(0713新增)
症状:VN 图片中部分行(如 PER、JNB)标注 暂时封舱,其他说明列含 二程窄体/二程宽体/二程1宽/二程天天宽。
规则:
暂时封舱不是停飞,价格仍然存在,整行保留,备注中体现该状态。- 频次仅在有明确
天天字样时输出Daily(如天天窄体、天天宽体、二程天天宽);二程窄体/二程宽体/二程1宽等无明确数字时频次留空,整句放入 Remark。 - 左侧标注
HAN/SGN中转的区块,跳转点统一填HAN,SGN;直达行留空。 - 货型统一为
1:1,散托类型散货/托盘。
九、脚本模板分布(使用时取最新版本)
| 路线 | 模板脚本 |
|------|---------|
| LHR | extract_eternity_muca_lhr.py |
| TPE | extract_eternity_czck_tpe.py |
| BKK/SIN/HAN | extract_eternity_ck_bkksinhan.py |
| HAN(CA) | extract_eternity_ca_han.py |
| HKG | extract_eternity_ck_hkg.py |
| AMS | extract_eternity_czckca_ams.py |
| LAX | extract_eternity_czckca_lax.py |
| ORD | extract_eternity_czckcake_ord.py |
| FRA | extract_eternity_czckcalh_fra.py |
| JFK | extract_eternity_caqfke_jfk.py |
| NLU | extract_eternity_cz_nlu.py |
| YYZ | extract_eternity_czkemu_yyz.py |
| VN 越南 | extract_eternity_vn_hansgn.py |
| SGN(CZ) | extract_eternity_cz_sgn.py |
| NRT/KIX | extract_eternity_czck_nrtkix.py |
| ICN | extract_eternity_ckcz_icn.py |
| CZ腹舱直达 | extract_eternity_cz_cz.py |
| HO | extract_eternity_ho_ho.py |
| CK亚大线直飞 | extract_eternity_ck_ck.py |
十、印度/孟加拉/斯里兰卡 手动录入模式(0526新增)
10.1 触发场景
用户发送手动录入的价格文本(非图片),通常以"周二上午千亚印度仓报更新收货"起头。
10.2 索引表
| # | 触发词 | 价格编号 | 目的地 | 航司 | 起运港 | 条数基准 |
|---|--------|---------|--------|------|--------|---------|
| 17 | DEL | eternity_cxcims_del_001 / eternity_vnnh_del_001 / eternity_mu_del_001 / eternity_hgh_cx_del_001 | DEL | CX/CI, VN/NH, MU, CX(HGH) | PVG/HGH | 6/6/6/6 |
| 18 | BOM | eternity_cxcims_bom_001 / eternity_nhmhvn_bom_001 / eternity_hgh_cx_bom_001 | BOM | CX/CI, NH/MH/VN, CX(HGH) | PVG/HGH | 6/6/6 |
| 19 | MAA | eternity_cx_maa_001 / eternity_mh_maa_001 | MAA | CX, MH | PVG | 6/10 |
| 20 | BLR | eternity_cx_blr_001 | BLR | CX | PVG | 6 |
| 21 | HYD | eternity_cx_hyd_001 | HYD | CX | PVG | 6 |
| 22 | CMB | eternity_cx_cmb_001 | CMB | CX | PVG | 6 |
| 23 | DAC | eternity_cx_dac_001 | DAC | CX | PVG/HGH | 4/1 |
10.3 通用规则
- 生效日期:从文本日期(如"周二")推导,当天或次日
- 货型转换:平托→1:1(托盘), 平散→1:1(散货), 1:250/1:300/1:500/1:1000 保留
- 比重链式:1:1→1:250→1:300→1:500→1:1000→9999
- 45KG 默认留空(手动录入通常不报45KG价)
- 所有重量段(100/300/500/1000)填充同一价格(除非明确标注)
10.4 特殊航线规则
CMB ⚠️ 复杂格式
「平29」= 全重量段同价 29(不属于 200KG 起限制) 「200KG起 1:200 27」= 45KG/100KG 留空,300/500/1000=27 结构:
抛货区(各自独立区间,全段同价):
1:80(0→80), 1:100(0→100), 1:120(0→120)
平货区(链式):
1:1(0→200) — 全段同价
1:200(200→300) — 45/100空
1:300(300→9999) — 45/100空
DAC ⚠️ 复杂格式
抛货: 1:120(0→120), 1:100(0→100), 1:80(0→80)
普货: "+100 15" = 100KG重量段价格=15 ⚠️
"+300 14.5" = 300KG=14.5(不是比重!)
城市差异:上海有抛货+普货,杭州仅有普货(无抛货 1:80-1:120)
MH-MAA ⚠️ 泡托/泡散
平托(1:1) → 1:80泡托 → 1:100泡托 → [链式1:250-1:1000]
平散(1:1) → 1:80泡散 → 1:100泡散 → [同上链式]
泡货插入低比重档,改变链式结构。
10.5 常见坑
坑14:CMB「平」全段同价 ≠ 200KG起限制(0526新增)
「平29 200KG起 1:200 27」中,「平29」是不属于 200KG 起的独立条目, 全重量段同价 29。仅有「1:200」和「1:300」受 200KG 起限制。
坑15:「+100」在 DAC 中是重量段,非比重(0526新增)
手动录入文本中「+100 15」表示 100KG 重量段价格=15, 和「1:100」完全不同。不能当成货型处理。
坑16:泡托/泡散改变链式比重结构(0526新增)
MH-MAA 中「1:80泡托」「1:100泡托」是独立的低比重档(0-100区), 与标准链式「0→250→300→500→1000→9999」结构不同。
坑17:城市间航线覆盖不全(0526新增)
CX-DAC 抛货仅上海有,杭州只有普货部分。 不能默认所有城市都有全部货型。
10.6 脚本模板
| 路线 | 模板脚本 |
|------|---------|
| 印度全线 | extract_eternity_india_0526.py |
🔴 坑18:复制旧数据当「不变」→ 全部价格错误(0608教训)
严重错误案例:0608 批次提取短航线9条时,凭肉眼扫一眼图片就标记「与0601不变」,直接复制了 0601 脚本的数据,导致 NLU 和 LAX 两条远程航线价格被严重低估。
实际情况:
- NLU: 0601 为 38/41/45/49/…,0608 实际为 43/47/53/59/…(涨+5~+12)
- LAX: 0601 为 36/38/42/48/…,0608 实际为 39/41/45/51/…(涨+3~+5)
- 其余7条短航线(BKK/SIN/HAN/CA HAN/HKG/TPE/SGN/VN/NRTKIX)确实不变
铁律:
- ❌ 禁止凭「看起来一样」复制旧数据
- ✅ 每个新批次必须逐格 OCR 核实全部价格
- ✅ 标记「不变」前必须跑 RapidOCR,逐行逐列对比
- ✅ 手工录入脚本中的 data 数组必须来自本次 OCR 结果,不是旧脚本复制
- ✅ 看到“单询 / 单询价 / 价格空白”时整行跳过,不生成任何重量段价格
🔴 坑19:散托类型/增量全量硬编码,未逐行提取「其他说明」列(0608教训)
错误案例:NLU 和 LAX 脚本中 '散托增量': 2 和 '散托类型': '散货/托盘' 在 records.append() 中对所有行硬编码,完全忽略了图片「其他说明」列的逐行差异。
实际情况(NLU):
- 1:80~1:200 其他说明「托盘+2元/kg」→ 散货, 增量=2
- 1:250~1:300 其他说明「托盘+1元/kg」→ 散货, 增量=1(⚠️ 与上方不同)
- 1:400~1:1000 无托盘+N / 托散同价 → 散货/托盘, 增量=空
修复方式:data 数组中每行独立声明 st_type 和 increment,records.append() 使用行级值而非全局常量。
铁律:
- ❌ 禁止在 records.append() 中硬编码
'散托增量': 2或'散托类型': '散货/托盘' - ✅ data 数组中每行必须包含独立的散托类型和散托增量字段
- ✅ 「其他说明」列有「托盘+N」→ st='散货', inc=N
- ✅ 「其他说明」列为空或「托散同价」→ st='散货/托盘', inc=''
经验10:ETERNITY 提取验证清单 ✅
每次 ETERNITY 提取完成后必须核对:
- 每条航线的价格是否来自当前批次图片(非旧批次复制)
- NLU/LAX/FRA/AMS/LHR/JFK/ORD/YYZ 等远程航线价差是否合理
- 散托增量(托盘+N)是否正确提取,逐行对照「其他说明」列,禁止全局硬编码
- 散托类型:有托盘+N → 散货,无 → 散货/托盘
- 45KG 列是否按图片正确处理(有/无/N/A)
- 频次是否清洗干净(无中文杂质)
- "单询"行是否已跳过;
靠45/50等说明文字不得误填 45KG 价格列 - 底部黄色转运表(若图片存在)是否已按坑22 转为转运点行:跳转点=空运到达机场、转运点=卡车终点、价格列全空;欧线图(LHR/FRA/AMS/FCO/BCN/MAD/MXP 等)默认检查。
Scan to join WeChat group