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

多站点医疗爬虫的可复用Beautiful Soup解析方案咨询

解决方案

一、用JSON配置处理嵌套HTML解析

要让非技术同事能通过JSON配置定义嵌套解析规则,你可以设计一套支持层级结构的配置格式,核心用children字段描述嵌套元素的解析逻辑。

示例JSON配置

针对你提到的期刊站点,配置可以这么写:

{
  "site_id": "paediatrieschweiz",
  "root_selector": ".journal-issues",
  "extract": {
    "issues": {
      "selector": ".issue-item",
      "children": {
        "issue_name": {
          "selector": ".issue-title",
          "type": "text"
        },
        "article_count": {
          "selector": ".article-count",
          "type": "text",
          "parser": "int"
        },
        "articles": {
          "selector": ".article-item",
          "children": {
            "title": {
              "selector": ".article-title",
              "type": "text"
            },
            "authors": {
              "selector": ".article-authors",
              "type": "text"
            }
          },
          "is_list": true
        }
      },
      "is_list": true
    }
  }
}
  • selector: BeautifulSoup支持的CSS选择器(可扩展支持XPath)
  • type: 提取类型,比如text(文本内容)、attr:href(标签属性)
  • parser: 可选的转换函数(比如转整数、清理字符串)
  • is_list: 标记当前选择器匹配多个元素,需要遍历处理
  • children: 嵌套的子元素解析规则

Python解析逻辑示例

用递归函数处理嵌套配置:

from bs4 import BeautifulSoup

# 安全的解析器映射表,替代eval避免风险
PARSER_MAP = {
    "int": int,
    "strip": lambda x: x.strip(),
    "lower": lambda x: x.lower()
}

def parse_element(soup, config):
    elements = soup.select(config["selector"])
    if not elements:
        return None
    
    if config.get("is_list", False):
        result = []
        for elem in elements:
            item = {}
            for key, child_config in config["children"].items():
                item[key] = parse_element(elem, child_config)
            result.append(item)
        return result
    else:
        elem = elements[0]
        # 提取内容
        if config["type"].startswith("attr:"):
            attr_name = config["type"].split(":")[1]
            value = elem.get(attr_name, "")
        else:
            value = elem.get_text(strip=True)
        
        # 应用转换规则
        if "parser" in config:
            parser = PARSER_MAP.get(config["parser"])
            if parser:
                value = parser(value)
        return value

# 使用示例
soup = BeautifulSoup(html_content, "html.parser")
# 加载JSON配置(比如用json.load)
config = {}
report_data = parse_element(soup, config["extract"]["issues"])

二、自定义解析代码的存储与按需导入

如果部分站点结构过于复杂,JSON配置无法覆盖,就用每个站点单独的parse.py存储自定义逻辑,再通过动态导入实现按需加载。

目录结构建议

scrapers/
├── paediatrieschweiz/
│   └── parse.py
├── cardiology_journal/
│   └── parse.py
└── ...

每个parse.py必须实现统一的入口函数,比如generate_report(soup) -> dict,返回结构化的报告数据。

动态导入实现

用Python的importlib模块加载指定站点的解析模块:

import importlib.util
import os

def load_custom_parser(site_id):
    parser_path = os.path.join("scrapers", site_id, "parse.py")
    if not os.path.exists(parser_path):
        raise ValueError(f"未找到站点 {site_id} 的解析代码")
    
    # 动态加载模块
    spec = importlib.util.spec_from_file_location(f"{site_id}_parser", parser_path)
    parser_module = importlib.util.module_from_spec(spec)
    spec.loader.exec_module(parser_module)
    
    # 返回统一入口函数
    return parser_module.generate_report

# 使用示例
parser = load_custom_parser("paediatrieschweiz")
report_data = parser(soup)

混合方案建议

你可以把两种方式结合:优先用JSON配置解析,对于复杂站点,在站点配置里标记parser_type: "custom",主程序根据这个字段自动选择用配置解析还是加载自定义代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.16 07:10:32