news 2026/10/9 18:10:22

Python快递分拣工具

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
Python快递分拣工具

这是快递分拣工具,输入地址按设定的规则自动匹配到对应的配送站点。

```python

# -*- coding: utf-8 -*-

"""

快递按收货地址自动分拣

核心思路:每条规则描述一个站点负责的范围(省/市/区 + 关键词),

分拣时对所有规则打分,取「优先级最高、匹配最精确」的那条。

"""

import re

from collections import defaultdict

from dataclasses import dataclass

from typing import Iterable, List, Optional, Sequence, Tuple

# ---------------- 1. 地址归一化 ----------------

_FULL_TO_HALF = str.maketrans(

"0123456789"

"ABCDEFGHIJKLMNOPQRSTUVWXYZ"

"abcdefghijklmnopqrstuvwxyz",

"0123456789"

"ABCDEFGHIJKLMNOPQRSTUVWXYZ"

"abcdefghijklmnopqrstuvwxyz",

)

def normalize(address: str) -> str:

"""全角转半角 + 去掉空白和常见分隔符,

让「北京市 朝阳区」「北京市,朝阳区」和「北京市朝阳区」等价。"""

if not address:

return ""

s = address.translate(_FULL_TO_HALF)

return re.sub(r"[\s,,.。;;、\-—_/\\|()()【】\[\]]+", "", s)

# ---------------- 2. 分拣规则 ----------------

@dataclass

class Rule:

"""一条分拣规则:某个站点负责的地址范围"""

site: str # 目标配送站 / 分拨中心

province: str = ""

city: str = ""

district: str = ""

keywords: Tuple[str, ...] = () # 街道、乡镇、园区等

priority: int = 0 # 越大越优先,用于强制覆盖

def __post_init__(self):

# 规则里的地址同样要归一化,保证和收件地址"同一套写法"

self.province = normalize(self.province)

self.city = normalize(self.city)

self.district = normalize(self.district)

self.keywords = tuple(normalize(k) for k in self.keywords if k)

def match_score(self, addr: str) -> Optional[int]:

"""addr 必须已归一化。命中返回得分(越高越精确),不命中返回 None。

打分逻辑:

- 规则里填写的省 / 市 / 区,必须全部出现在地址中(硬约束);

- 命中的层级越多,分数越高(省 100、市 50、区 20);

- 关键词每命中一个 +5,用于同区内再细分。

"""

if not any((self.province, self.city, self.district, self.keywords)):

return None

score = 0

for value, weight in ((self.province, 100), (self.city, 50), (self.district, 20)):

if value:

if value not in addr:

return None

score += weight

for kw in self.keywords:

if kw in addr:

score += 5

return score or None

# ---------------- 3. 分拣器 ----------------

@dataclass

class SortResult:

address: str

site: str

matched: bool

rule: Optional[Rule] = None

class AddressSorter:

def __init__(self, rules: Sequence[Rule], default_site: str = "人工分拣区"):

self.rules = list(rules)

self.default_site = default_site

def sort(self, address: str) -> SortResult:

addr = normalize(address)

best_rule, best_key = None, None

for rule in self.rules:

score = rule.match_score(addr)

if score is None:

continue

key = (rule.priority, score) # 先比优先级,再比精确度

if best_key is None or key > best_key: # 同分时先注册的规则胜出

best_rule, best_key = rule, key

if best_rule is None:

return SortResult(address, self.default_site, False, None)

return SortResult(address, best_rule.site, True, best_rule)

def sort_batch(self, addresses: Iterable[str]) -> List[SortResult]:

return [self.sort(a) for a in addresses]

# ---------------- 4. 规则配置 + 使用示例 ----------------

RULES: List[Rule] = [

# 北京:朝阳区内再细分出「望京站」

Rule(site="北京-望京站", province="北京", city="北京", district="朝阳区",

keywords=("望京", "酒仙桥", "大山子", "阜通", "来广营")),

Rule(site="北京-朝阳站", province="北京", city="北京", district="朝阳区"),

Rule(site="北京-海淀站", province="北京", city="北京", district="海淀区"),

# 上海

Rule(site="上海-虹桥站", province="上海", city="上海", district="闵行区",

keywords=("虹桥", "华漕", "七宝")),

Rule(site="上海-浦东站", province="上海", city="上海", district="浦东新区"),

# 广东

Rule(site="广州-天河站", province="广东", city="广州", district="天河区"),

Rule(site="深圳-南山站", province="广东", city="深圳", district="南山区"),

# 注意:全国有两个「朝阳」——靠省市区三级约束区分

Rule(site="辽宁-朝阳站", province="辽宁", city="朝阳", district="双塔区"),

]

if __name__ == "__main__":

sorter = AddressSorter(RULES, default_site="北京-人工分拣")

addresses = [

"北京市朝阳区望京街道阜通东大街6号",

"北京市朝阳区建国路88号SOHO现代城",

"北京市海淀区中关村大街1号",

"上海市闵行区虹桥火车站出发层",

"上海市浦东新区世纪大道100号",

"广东省广州市天河区体育西路103号",

"广东省深圳市南山区科技园南区",

"辽宁省朝阳市双塔区新华路1号",

"火星基地一号舱", # 匹配不到 → 兜底

]

results = sorter.sort_batch(addresses)

print("=== 逐单分拣结果 ===")

for r in results:

flag = "✔" if r.matched else "✘"

print(f"{flag} {r.address} -> {r.site}")

print("\n=== 按站点汇总(实际装车用)===")

groups = defaultdict(list)

for r in results:

groups[r.site].append(r.address)

for site, addrs in groups.items():

print(f"\n【{site}】共 {len(addrs)} 单")

for a in addrs:

print(f" - {a}")

```

分拣逻辑与操作说明

这段代码就像一个智能分拣员,收到地址后按您定义的规则自动匹配站点,并给出最终去向。

· 地址归一化:先把全角字符、空格和标点统一成半角并去掉分隔符,避免“北京市 朝阳区”和“北京市朝阳区”被当成不同地址。

· 规则匹配:每条规则包含省、市、区、关键词和优先级;省市区必须全部命中才有效,命中的层级越多得分越高,关键词每命中一个再加分。

· 判定与兜底:所有规则中得分最高且优先级最高的胜出;如果没有任何规则命中,自动归入“人工分拣区”。

· 结果展示:逐单显示匹配结果(✔或✘),并按站点汇总每个配送站需要装车的订单。

---

优化建议: 规则配置集中在代码末尾的 RULES 列表中,可以按同样的格式增删站点和区域;批量测试地址就在下面的 addresses 列表里修改。

文章仅供参考用。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/9 18:09:57

游戏引擎渲染系统三层架构实战解析

1. 这不是教科书里的渲染管线图,而是一套真正跑在百万行代码项目里的骨架“游戏引擎架构深度解析(二):渲染系统架构”——看到这个标题,你脑子里浮现的可能是DX12/Vulkan的管线状态对象、RenderGraph的节点拓扑&#x…

作者头像 李华
网站建设 2026/10/9 18:04:46

SQL Server性能诊断实战:执行计划、锁阻塞与索引失效深度解析

简介:本资源是专为SQL Server数据库工程师、DBA及求职者打造的高频面试题精编集,覆盖数据库原理、T-SQL实战与高阶运维三大维度,直击技术面试核心考点。内容系统梳理23个基础知识要点(如主键/外键本质、索引类型与最左前缀原则&am…

作者头像 李华
网站建设 2026/10/9 18:04:43

MATLAB与STK联合仿真指南:从轨道建模到覆盖分析全流程

简介:面向航天、通信与遥感领域的工程师及科研人员,MATLAB/STK联合仿真工具包定位清晰:解决MATLAB调用STK接口、构建场景并获取仿真结果的核心需求,特别聚焦卫星相关的轨道与覆盖分析任务。压缩包体积约6KB,共5个文件&…

作者头像 李华
网站建设 2026/10/9 18:04:41

花卉图像识别实战:从数据清洗到手机端推理的完整链路

简介:本资源是一份面向本科毕业设计与课程设计的深度学习实践项目,聚焦花卉图像识别这一典型计算机视觉任务,适合具备Python基础与初步深度学习认知的学习者开展实战训练。压缩包共10个文件,含4个核心Python源码(main.…

作者头像 李华
网站建设 2026/10/9 18:04:36

SQL Server 2000 实操指南:老系统迁移、离线审计与兼容性验证

简介:本资源为微软SQL Server 2000(SQL2K)完整安装包及配套技术资料合集,面向数据库初学者、运维工程师及遗留系统维护人员,用于本地环境搭建、历史系统复现、兼容性测试与经典数据库原理学习。压缩包为ZIP格式&#x…

作者头像 李华
网站建设 2026/10/9 18:03:54

SQLite3易语言支持库1.0升级2.x编码兼容指南

简介:本资源是面向易语言开发者的数据持久化增强工具包,专为需要在Windows平台集成SQLite3数据库功能的中高级程序员设计,解决原生支持库功能不足、多线程事务控制薄弱、记录集生命周期管理不明确等实际开发痛点。压缩包共413个文件&#xff…

作者头像 李华