本文介绍一种基于行分割与顺序切片的稳健方法,从结构化文本中准确提取网球比赛双方的逐局得分,避免因全局数字提取导致的顺序错乱问题。
本文介绍一种基于行分割与顺序切片的稳健方法,从结构化文本中准确提取网球比赛双方的逐局得分,避免因全局数字提取导致的顺序错乱问题。
在处理网球赛事原始文本(如直播日志或爬虫抓取的比分段)时,一个常见但关键的需求是:严格保持数值在原文中出现的物理顺序,并据此区分两位选手的局分(games)。原方案使用 split() 全局切分后通过步长切片([::2] / [1::2])分配数值,本质上假设“p1 和 p2 的分数严格交替出现”,而实际文本结构是先集中列出 p1 所有局分,再集中列出 p2 所有局分——这直接导致 p1_score = "4 6" 这类逻辑错误。
正确的解法应尊重文本的行级结构语义:观察示例可知,每个数字独占一行,且 p1 分数位于 D. Altmaier 和 M. Kecmanovic 之间,p2 分数位于 M. Kecmanovic 之后、最终总结句之前。因此,我们应优先利用换行符进行分割,再按顺序归组:
def extract_player_scores(row):
# 按行分割,过滤出纯数字行(去除空行和非数字行)
lines = row['score'].splitlines()
numeric_lines = [line.strip() for line in lines if line.strip().isdigit()]
# 将所有连续数字行均分为两组:前半为 p1,后半为 p2
n = len(numeric_lines)
if n == 0:
return pd.Series(["", ""])
mid = n // 2
p1_scores = " ".join(numeric_lines[:mid])
p2_scores = " ".join(numeric_lines[mid:])
return pd.Series([p1_scores, p2_scores])
# 应用到 DataFrame
df_final[['p1_score', 'p2_score']] = df_final.apply(extract_player_scores, axis=1)✅ 为什么此方法更可靠?
- splitlines() 保留了原始文本的垂直布局逻辑,每行一个数字对应一局比分;
- strip().isdigit() 精准识别独立数字行,避免误匹配时间(如 "01:33:55")或混合字符串;
- 顺序切片 [:mid] 和 [mid:] 直接映射“先 p1 后 p2”的语义结构,不依赖数字位置奇偶性。
⚠️ 注意事项:
- 若文本中存在额外干扰数字(如赛制轮次 "Round of 16" 中的 16),需先做预处理(例如用正则定位 Altmaier 到 Kecmanovic 之间的区块);
- 对于非对称局数(如抢七局 7-6 可能产生 3 个数字),n//2 自动向下取整,确保 p1 得到前 ⌊n/2⌋ 个值,符合多数网球比分格式(双方局数通常相等,或 p2 多一局);
- 生产环境建议增加异常处理(如空输入、无数字行),提升鲁棒性。
该方法简洁、可读性强,且完全脱离对字符串全局模式的脆弱依赖,是结构化文本中顺序敏感型数值提取的典型实践范式。










