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

如何用BeautifulSoup从随机HTML片段提取指定字段信息

HTML元数据字段提取优化方案

需求说明

需要从结构随机的HTML片段中提取以下6类元数据,缺失字段设为None:
["badge", "issue", "date", "publisher", "city", "page"]

当前输出 vs 预期输出

当前代码仅能提取前3类字段,输出示例:

[None, 'nro 4 A.', '6.12.1939', None, None, None]  # html_1
[None, None, '1905', None, None, None]             # html_2
['22', 'nro 12 ZZ', '10.2016', None, None, None]   # html_3

预期完整输出:

[None, 'nro 4 A.', '6.12.1939', 'JR 10', None, 'sivu 1']                     # html_1
[None, None, '1905', 'Aksel Paul', 'Helsinki', 'page 63']                    # html_2
['22', 'nro 12 ZZ', '10.2016', 'Arbetarförlaget Ab', 'Stockholm', 'sida 20'] # html_3

问题分析

现有代码仅处理了badge、issue、date,剩余字段(publisher、city、page)因在HTML中位置随机,soup.find_all("span", class_="ng-star-inserted")返回的列表长度不固定,无法通过固定索引提取。

优化实现方案

核心思路:通过文本特征匹配识别剩余字段,而非依赖固定位置。具体步骤:

  1. 初始化结果列表,默认全为None
  2. 提取badge:基于固定class定位
  3. 提取issue和date:从font-weight-bold容器下的元素中,通过文本关键词(nro)和日期格式特征区分
  4. 提取剩余字段:遍历所有ng-star-inserted元素,排除已提取的issue和date,再通过文本特征匹配page,剩余文本按顺序映射到publisher和city

完整代码

from bs4 import BeautifulSoup

def extract_metadata(html):
    # 初始化结果列表,对应顺序:badge, issue, date, publisher, city, page
    desired_list = [None] * 6
    soup = BeautifulSoup(html, "lxml")
    
    # 1. 提取badge
    badge = soup.find("span", class_="badge badge-secondary ng-star-inserted")
    if badge:
        desired_list[0] = badge.text.strip()
    
    # 2. 提取issue和date
    fwb = soup.find("span", class_="font-weight-bold")
    if fwb:
        issue_date_elements = fwb.select("span.ng-star-inserted")
        for el in issue_date_elements:
            text = el.text.strip()
            if "nro" in text.lower():
                desired_list[1] = text
            # 判断日期:包含数字和分隔符(.),或纯年份
            elif any(char.isdigit() for char in text):
                desired_list[2] = text
    
    # 3. 提取publisher、city、page
    all_ng_elements = soup.find_all("span", class_="ng-star-inserted")
    # 收集已识别的文本,用于排除重复
    identified_texts = [t for t in desired_list if t is not None]
    remaining_texts = []
    
    for el in all_ng_elements:
        text = el.text.strip()
        if text and text not in identified_texts:
            remaining_texts.append(text)
    
    # 匹配page字段(含sivu/page/sida等关键词)
    page_keywords = {"sivu", "page", "sida"}
    for idx, text in enumerate(remaining_texts):
        if any(keyword in text.lower() for keyword in page_keywords):
            desired_list[5] = text
            remaining_texts.pop(idx)
            break
    
    # 剩余文本按顺序分配给publisher和city
    if len(remaining_texts) >= 1:
        desired_list[3] = remaining_texts[0]
    if len(remaining_texts) >= 2:
        desired_list[4] = remaining_texts[1]
    
    return desired_list

代码说明

  • badge提取:保持原有逻辑,通过特定class定位
  • issue/date提取:修复原代码的覆盖问题,通过关键词nro识别issue,通过数字特征识别日期(支持纯年份或带分隔符的格式)
  • 剩余字段提取:
    • 先收集所有未被识别的ng-star-inserted文本,排除已提取内容
    • 通过多语言关键词匹配page(适配不同地区的页面标识)
    • 剩余文本按顺序填充publisher和city,适配不同HTML的结构差异

测试验证

将三段HTML分别传入extract_metadata函数,即可得到预期的完整输出。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 15:51:51