You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

MARC格式文本提取问题:无法捕获重复的¶7146$u字段值

MARC格式字符串重复区域提取问题解决

问题背景

现有一个名为df的DataFrame,其中text列每行是一条MARC格式的字符串,示例如下:

d20s 22 i2as¶001VNINDEA455133910000005¶008180529c 1996 frmmm wz 7b ¶009se z 1 m mm c¶008a ¶008at ¶008ap ¶008a ¶0441 $a2609-2565$c2609-2565¶0410 $afre$aeng$apor ¶0569 $a2758-8965$c4578-7854¶0300 $a789$987$754 ¶051 $atxt$asti$atdi$bc¶110 $317737535$w20..b.....$astock market situation¶3330 $aimport and export agency ABC¶7146 $q1$uwwww.abc.org$ma1¶7146 $q9$uAgency XYZ¶8799 $q1$uAgency ABC$fHTML$

需要提取:

  • ¶7146区域中$u后的所有内容
  • ¶0441区域中$c后的内容

期望结果如下:

¶7146$u¶0441$c
wwwww.abc.org2609-2565
Agency XYZ2609-2565

用户编写的Python代码如下:

import os
import pandas as pd
import numpy as np
import requests


df = pd.read_csv('dataset.csv')

def extract(text, start_pattern, sc):
    ist = text.find(start_pattern)
    if ist < 0:
        return ""
    ist = text.find(sc, ist)
    if ist < 0:
        return ""
    im = text.find("$", ist + len(sc))
    iz = text.find("¶", ist + len(sc))
    if im >= 0:
        if iz >= 0:
            ie = min(im, iz)
        else:
            ie = im
    else:
        ie = iz
    if ie < 0:
        return ""
    return text[ist + len(sc): ie]

def extract_text(row, list_in_zones):
    text = row["text"]
    if pd.isna(text):
        return [""] * len(list_in_zones)
    patterns = [("¶" + p, "$" + c) for p, c in [zone.split("$") for zone in list_in_zones]]
    return [extract(text, pattern, sc) for pattern, sc in patterns]


list_in_zones = ["7146$u", "0441$u", "200$y"]


df[list_in_zones] = df.apply(lambda row: extract_text(row, list_in_zones),
                             axis=1,
                             result_type="expand")

df.to_excel("extract.xlsx", index = False)

但代码仅能提取到¶7146$u的第一个值wwww.abc.org,无法捕获重复出现的Agency XYZ。

补充规则:每个区域以开头(如¶7146、¶0441),字段以$开头(如$u、$c),字段内容结束于$或。

代码问题分析

  1. 单匹配逻辑限制:原extract函数仅执行一次find操作,只会定位到第一个匹配的目标区域,不会遍历字符串中所有重复出现的同编号区域(比如示例中的两次¶7146)。
  2. 需求与参数不匹配:list_in_zones中写的是"0441$u",但实际需求是提取0441$c的内容,参数设置错误。
  3. 结果格式不兼容多行输出:原函数设计为返回单个字符串,无法返回多个匹配值,无法满足将重复值拆分为多行的需求。

修改后的解决方案

核心思路

  1. 按分割MARC字符串,拆分出所有独立区域;
  2. 遍历每个区域,筛选出目标编号的区域(如7146、0441);
  3. 在目标区域内,提取所有目标字段(如$u、$c)的内容;
  4. 整理结果,将多值提取结果转换为可扩展的格式,实现一行输入对应多行输出。

修改后的代码

import pandas as pd

df = pd.read_csv('dataset.csv')

def extract_all_values(text, zone_code, field_code):
    """提取指定区域中指定字段的所有值"""
    if pd.isna(text):
        return []
    # 按¶分割所有区域,跳过空的片段
    zones = [zone.strip() for zone in text.split('¶') if zone.strip()]
    results = []
    for zone in zones:
        # 检查区域是否以目标编号开头
        if zone.startswith(zone_code):
            # 提取当前区域内的所有目标字段内容
            pos = 0
            field_prefix = f'${field_code}'
            while True:
                # 查找当前位置后的字段
                field_start = zone.find(field_prefix, pos)
                if field_start == -1:
                    break
                # 计算字段内容的起始位置
                content_start = field_start + len(field_prefix)
                # 查找字段内容的结束位置(下一个$或区域末尾)
                content_end = zone.find('$', content_start)
                if content_end == -1:
                    content_end = len(zone)
                # 提取内容并去重(可选,根据需求)
                value = zone[content_start:content_end].strip()
                if value:
                    results.append(value)
                # 更新位置,继续查找下一个同字段
                pos = content_end
    return results

def process_row(row):
    """处理单行数据,返回所有提取结果的组合"""
    text = row["text"]
    # 提取7146$u的所有值
    u_values = extract_all_values(text, '7146', 'u')
    # 提取0441$c的所有值(如果有多个0441区域,也会全部提取)
    c_values = extract_all_values(text, '0441', 'c')
    # 处理结果对齐:如果某类值数量少,用最后一个值填充(或空值,根据需求调整)
    max_len = max(len(u_values), len(c_values))
    # 填充至最大长度
    u_filled = u_values + [u_values[-1]]*(max_len - len(u_values)) if u_values else ['']*max_len
    c_filled = c_values + [c_values[-1]]*(max_len - len(c_values)) if c_values else ['']*max_len
    # 返回多行数据的列表
    return pd.DataFrame({'¶7146$u': u_filled, '¶0441$c': c_filled})

# 处理每一行并合并结果
final_df = pd.concat([process_row(row) for _, row in df.iterrows()], ignore_index=True)

# 保存结果
final_df.to_excel("extract.xlsx", index=False)

代码说明

  • extract_all_values函数:负责遍历所有区域,收集指定区域内指定字段的所有值,支持同一区域内多个相同字段的提取;
  • process_row函数:处理单行MARC数据,提取目标字段的所有值,并对齐结果长度(确保7146的每个值都对应0441的内容);
  • 最终通过pd.concat将每行的多行结果合并成最终的DataFrame,符合期望的输出格式。

内容的提问来源于stack exchange,提问作者THOMAS

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 16:15:33