Back to skills
extension
Category: Data & AnalyticsNo API key required

中集深圳空运价格提取

CIMC 深圳空运价格提取规则。当用户提供 CIMC 深圳价格文件(.xls 格式,命名含"中集(深圳)")时使用。触发词:CIMC 深圳、中集深圳、cimc_szx、深圳MAY。

personAuthor: user_17da570ahubcommunity

CIMC 深圳价格提取 Skill

提取 CIMC 深圳运价表 → 24列标准输出 → 上传 WPS。

⚠️ 铁律:仅提取用户最新提交文件,禁止复制历史数据

  • 禁止查看/引用/复制任何历史脚本中的 price/data 数组
  • 禁止从历史输出文件直接读取数据
  • 禁止硬编码历史文件路径作为源文件
  • 每次提取必须从用户当前提交文件全新读取
  • 有就是有,没有就是没有:不得用历史数据填补缺失值

一、核心参数

| 参数 | 值 | |------|-----| | 起始港 | SZX | | 价格编号 | cimc_szx_001 | | 来源 | CIMC | | 引擎 | xlrd(.xls) | | 基准日期 | 2026-05-18(>=此日期才提取) |


二、与广州版的关键差异

| 差异点 | 广州 | 深圳 | |--------|------|------| | 起始港 | CAN | SZX | | 比重推导 | ratio_engine.py | 内置 chain_ratio() | | 合并单元格 | openpyxl merge_map | get_merged_value() 函数 | | 转运过滤 | 按"转运"关键词 | 按行特征判别 | | Sheet 数 | 16 | 17 | | 散托增量默认 | 各Sheet不同 | 仅 TK/CA/D0 有默认值 |


三、强制流程

1. 确认源文件路径(用户提交的 .xls 文件)
2. xlrd 加载 → 逐个 Sheet 提取
3. 合并单元格处理 → 转运数据过滤
4. 按 (dest, transit, eff_date) 分组收集
5. 链式比重推导 → 生成24列
6. 去重 → 保存 → 上传 WPS

四、深圳 Sheet 配置(17 个)

sheets = [
    ('TK', 'TK'), ('CA 直航', 'CA'), ('CA 欧洲中转', 'CA'),
    ('CA 美线中转', 'CA'), ('CZ 直航', 'CZ'), ('CZ 中转', 'CZ'),
    ('CZ ORD', 'CZ'), ('HU', 'HU'), ('D0 欧洲', 'D0'),
    ('D0 美线', 'D0'), ('JG BKK SGN', 'JG'), ('O3 LAX', 'O3'),
    ('O3 深圳始发', 'O3'), ('CI', 'CI'), ('BR', 'BR'),
    ('K6', 'K6'), ('WW KUL', 'WW'),
]

Sheet 级散托增量 ⚠️ 已废弃

# ⚠️ 2026-06-01 起:不再使用 Sheet 级默认增量!
# 散托增量仅从备注显式 +N 提取,无 +N → 增量空
# SHEET_INCREMENT 仅用于标记特定 Sheet 的默认散托类型(无实际作用,保留兼容)
SHEET_INCREMENT = {}  # 全部清空,不设默认值

五、合并单元格处理(get_merged_value

深圳版 不用 openpyxl merge_map,直接用 xlrd 的 merged_cells 属性:

def get_merged_value(ws, row_idx, col_idx):
    for (r_lo, r_hi, c_lo, c_hi) in ws.merged_cells:
        if r_lo <= row_idx < r_hi and c_lo <= col_idx < c_hi:
            return ws.cell_value(r_lo, col_idx)  # 返回左上角值
    return ws.cell_value(row_idx, col_idx)

每行读取时同时保留 row(合并后)和 row_raw(原始值),用于:备注继承判断、空值区分。


六、转运数据过滤 ⚠️ 关键规则

深圳文件中含有转运辐射点价格表,必须过滤:

情况1row[0] 有值且非 SZX/PVG/CAN → 转运数据

情况2row[0] 为空,row[1] 是三字码但非 SZX,且 row[2]+row[3] 是数字 → 转运数据

正常价格行特征row[1] == 'SZX'(起运港)

if row0_str and row0_str not in ['SZX', 'PVG', 'CAN']:
    if row0_str not in ['区域', '深圳始发', '美线'] and not startswith('生效'):
        is_transit = True

七、数据分组与链式比重推导

7.1 分组键

key = (current_dest, current_transit, eff_date)
data_groups[key] = {'items': [], 'freq': '', 'st_type': '散货/托盘', ...}

7.2 链式推导(chain_ratio)— 不同于广州的 ratio_engine

# lt 档(<XXX): 泡货,按阈值升序
# 1:1 档: 接在 lt 链后,覆盖到第一个 gt 档
# gt 档(>XXX): 重货,按阈值升序,末档=9999

仅当存在 <XXX>XXX 时才走链式推导,否则每行独立输出 (0, 9999, cargo, ...)


八、散托类型与增量判断 ⚠️ 2026-06-01 修正

🚨 铁律:散托增量仅从备注显式 +N 提取,无 +N → 增量为空

  1. 优先卡板/托盘+N卡板+2/KG托盘+1/KG → 散货,增量=N
  2. 兜底任意+N(N ≤ 20):直达点+1/KG快件+1/KG → 散货,增量=N
  3. 无 +N 或 N > 20(如 +100KG+500KG 权重阈值)→ 散货/托盘,增量=空

增量解析函数

def parse_increment(remark, default=None):
    remark_str = str(remark) if remark else ''
    # 1️⃣ 优先卡板/托盘 +N
    m = re.search(r'(?:卡板|托盘)\s*\+(\d+(?:\.\d+)?)', remark_str)
    if m:
        return float(m.group(1))
    # 2️⃣ 兜底任意+N(≤20 排除权重阈值误匹配)
    m = re.search(r'\+(\d+(?:\.\d+)?)', remark_str)
    if m:
        val = float(m.group(1))
        if val <= 20:
            return val
    return default

### Sheet 级散托增量 ⚠️ 已废弃
# ⚠️ 2026-06-01 起:不再使用 Sheet 级默认增量!
# SHEET_INCREMENT = {}  # 全部清空,不设默认值
  1. 无 +N 备注 → 散货/托盘,增量=空

⚠️ 禁止行为

  • ❌ 使用 Sheet 级默认值硬塞增量(如 CA=2)
  • ❌ 无 +N 备注时赋值增量 > 0

st_type 更新优先级(关键)

if st_type == '散货':
    group['st_type'] = st_type      # 散货优先级最高,不被覆盖
elif st_type and group['st_type'] == '散货/托盘':
    group['st_type'] = st_type      # 仅在未确定时才更新

九、生效日期处理

if '生效时间' in row_str:
    eff = parse_date(row_str)         # 从"生效时间:YYYY-MM-DD"提取
    current_eff_date = eff

# 过滤 < 基准日期的数据
if current_eff_date and current_eff_date < datetime(2026, 5, 18):
    continue  # 跳过旧价格

十、多目的地格式

if '/' in dest:
    dest_parts = dest.split('/')         # CMB/MLE → ['CMB','MLE']
elif ' ' in dest:
    dest_parts = dest.split(' ')         # DXB DWC → ['DXB','DWC']
else:
    dest_parts = [dest]

# 统一用英文逗号拼接
dests = [','.join(dest_parts)]           # CMB,MLE

十一、输出格式

24列标准输出(HEADERS 直接用内联列表):

HEADERS = [
    '起始港', '目的港', '航司', '开始比重', '结束比重', '货型',
    '45KG', '100KG', '300KG', '500KG', '1000KG',
    '散托类型', '开始生效日期', '分泡', '频次', 'Remark',
    '跳转点', '转运点', '转运费增量值(RMB/KG)', '转运费最低收费(/票)', '备注',
    '来源', '价格编号', '散托增量'
]

⚠️ 列19-20必须使用标准名 '转运费增量值(RMB/KG)''转运费最低收费(/票)',禁止使用简写 '转运费1''转运费2'


十二、常见坑

坑1:合并单元格备注归属

备注归最后一行(比重最低行),xlrd 的 merged_cells 只返回第一行值。

坑2:多行备注 \n 处理

remark_full = str(remark).replace('\n', ' ').replace('\r', ' ')

坑3:st_type 覆盖问题

st_type='散货' 优先级最高,不被后续空备注覆盖。

坑4:转运数据误提取

必须严格检查 row[1] == 'SZX' 判断是否为正常价格行。

坑5:列名不标准

脚本内联 HEADERS 必须使用标准 24 列:'转运费增量值(RMB/KG)''转运费最低收费(/票)',禁止再用 '转运费1' / '转运费2'

坑6:Sheet 级默认增量错误赋值 🔴 0610修复

症状:无 +N 备注的行被赋值增量=2(如 CA 直航亚洲线、TK 全线) 原因:旧代码用 SHEET_INCREMENT 做默认值 fallback 修复:仅 parse_increment() 返回非 None 时才设增量,否则增量为空

坑7:多+N冲突 - 卡板优先 🔴 0601修复

症状:备注含「直达点+1/KG」+「卡板+2/KG」,结果取到+1而非+2 原因re.search 匹配第一个 +N = 直达点+1 修复parse_increment() 分两步:

  1. 优先 (?:卡板|托盘)\s*\+N
  2. 兜底任意 +N(N ≤ 20 排除 +100KG/+500KG 权重阈值)

坑8:鄂州机场代码 EZH→EHU 🔴 0601修复

症状:O3 鄂州始发 Sheet 目的地列填的是 EZH,但实际鄂州花湖机场三字码是 EHU 修复:Sheet 配置中 ('O3 鄂州始发', 'O3', 'EZH')('O3 鄂州始发', 'O3', 'EHU')


十三、脚本模板

脚本模板:/Users/hantao/WorkBuddy/oone/extract_cimc_szx.py 源文件:用户每次提交时指定

新批次时需更新:

  1. SRC 路径指向新文件
  2. 基准日期 datetime(2026, 5, 18) 改为文件日期
  3. Sheet 配置确认是否有新增/删减
  4. 运行 → 验证 → 上传 WPS