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

如何用BeautifulSoup在客户端进一步缩减DOM/HTML体积?

问题:如何进一步缩减HTML体积以适配GPT-4的Token限制?

我正在使用Playwright访问网页,在执行Playwright操作前希望最小化获取到的DOM。由于需要将内容发送至GPT-4 API,必须控制token数在4000以内,因此HTML越精简越好。

目前我已实现以下代码,可移除不必要标签、注释、非必要属性及空白字符,通常能缩减30-40%的DOM体积:

def minimize_html(html_content):
    soup = BeautifulSoup(html_content, 'html.parser')

    # Remove unnecessary tags
    for tag in soup.find_all(['style', 'script', 'meta', 'link']):
        tag.decompose()

    # Remove comments
    for element in soup(text=lambda text: isinstance(text, Comment)):
        element.extract()

    # Remove attributes except for form-related elements and href
    for tag in soup.find_all(True):
        if tag.name not in ['form', 'input', 'select', 'textarea', 'button', 'a']:
            tag.attrs = {}
        else:
            if tag.name == 'a':
                href = tag.attrs.get('href')
                tag.attrs = {'href': href} if href else {}

    # Minify HTML by removing whitespace
    clean_content = str(soup).replace('\n', '').replace('\r', '').strip()

    return clean_content

我的问题是:

  1. 还能移除哪些内容?我考虑截断超过200字符的文本以进一步缩减文本密集型网页的DOM体积。
  2. 有没有更优的客户端DOM体积缩减方法?

回答

一、可进一步移除的内容

  • 纯装饰性容器标签:移除<div>、<span>这类无实际语义、不含保留属性或关键文本的冗余容器;若不需要列表结构,可仅保留<li>内的文本,移除外层<ul>/<ol>标签。
  • 隐藏元素:移除带有hidden属性、display: none或visibility: hidden样式的元素,这类元素通常不包含核心内容。
  • 非核心文本:移除页脚版权信息、重复导航文本、广告文案等与业务无关的冗余文本。
  • 辅助表单元素:若不需要完整表单结构,可移除<label>、<fieldset>等非核心表单辅助标签,仅保留业务相关的控件。

二、文本截断的实现方案

截断长文本是针对文本密集型网页的有效优化手段,可在现有清理逻辑基础上新增文本节点处理:

from bs4 import BeautifulSoup, Comment

def truncate_long_text(text, max_length=200):
    if len(text) > max_length:
        return text[:max_length] + "..."
    return text

def minimize_html(html_content):
    soup = BeautifulSoup(html_content, 'html.parser')

    # 原有清理逻辑
    for tag in soup.find_all(['style', 'script', 'meta', 'link']):
        tag.decompose()
    for element in soup(text=lambda text: isinstance(text, Comment)):
        element.extract()
    for tag in soup.find_all(True):
        if tag.name not in ['form', 'input', 'select', 'textarea', 'button', 'a']:
            tag.attrs = {}
        else:
            if tag.name == 'a':
                href = tag.attrs.get('href')
                tag.attrs = {'href': href} if href else {}

    # 新增:截断长文本节点
    for text_node in soup.find_all(text=True):
        stripped_text = text_node.strip()
        if stripped_text:
            truncated_text = truncate_long_text(stripped_text)
            text_node.replace_with(truncated_text)

    # 压缩空白(比直接替换换行更彻底)
    clean_content = ' '.join(str(soup).split()).strip()
    return clean_content

可根据实际需求调整max_length参数,保留省略号避免语义丢失

三、客户端DOM缩减方法(Playwright端优化)

在Playwright中直接操作DOM,比先获取完整HTML再解析更高效,还能减少数据传输量:

  • 客户端直接移除冗余元素:页面加载完成后,通过page.evaluate()执行JS清理DOM:
    await page.evaluate("""
        // 移除样式、脚本、元标签等
        document.querySelectorAll('style, script, meta, link').forEach(el => el.remove());
        // 移除所有注释节点
        const comments = [];
        const walk = document.createTreeWalker(document.body, NodeFilter.SHOW_COMMENT);
        let comment;
        while (comment = walk.nextNode()) comments.push(comment);
        comments.forEach(c => c.remove());
        // 移除隐藏元素
        document.querySelectorAll('[hidden], [style*="display:none"], [style*="visibility:hidden"]').forEach(el => el.remove());
    """)
    
  • 仅提取核心区域HTML:如果只需要页面特定部分(如文章正文),直接定位目标元素获取HTML:
    core_html = await page.locator('article').inner_html()
    
  • 客户端压缩HTML:在浏览器端直接压缩HTML后再获取,减少传输体积:
    minimized_html = await page.evaluate("""
        return document.documentElement.outerHTML
            .replace(/<!--[\s\S]*?-->/g, '') // 移除注释
            .replace(/\s+/g, ' ') // 合并空白字符
            .trim();
    """)
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.14 06:47:44