h1到h6是语义层级标签,非视觉样式工具;每页仅一个h1作唯一主标题,h2–h6须严格逐级嵌套,跳级、乱序或滥用会损害可访问性与SEO。

提取 <h1></h1> 到 <h6></h6> 标题时,别依赖字体大小判断层级
很多人看到渲染后 <h2></h2> 比 <h3></h3> 小,就改用 <h3></h3> 当二级标题——这是语义错误。搜索引擎和屏幕阅读器只认标签名,不看 CSS 渲染结果。提取标题结构时,必须严格按文档中实际使用的 <h1></h1>–<h6></h6> 标签层级来建树,而不是根据视觉大小反推。
常见错误现象:
用正则直接匹配 <h></h> 但没处理闭合标签或自闭合变体(如 <h2></h2>);忽略嵌套在 <div> 或 <code><article></article> 内的标题,导致层级错乱。
实操建议:
• 优先用 DOM 解析器(如 Python 的 BeautifulSoup 或 JS 的 document.querySelectorAll('h1,h2,h3,h4,h5,h6'))而非正则提取标题
• 遍历时记录每个节点的 nodeName(如 'H2'),再转为数字层级(parseInt(nodeName.slice(1)))
• 若需保留文档顺序与嵌套关系,应同时提取父容器的 section、article 或 nav 等语义块
用 <p></p><div class="aritcle_card flexRow">
<div class="artcardd flexRow">
<a class="aritcle_card_img" href="/xiazai/skill10828" title="财经HTML高端海报生成"><img
src="https://img.php.cn/upload/skill/001/246/273/6adaf20dbae7c507.jpg" alt="财经HTML高端海报生成" ></a>
<div class="aritcle_card_info flexColumn">
<a href="/xiazai/skill10828" title="财经HTML高端海报生成">财经HTML高端海报生成</a>
<p>复杂得财经如何变成清晰,适合手机看的海报?如何加上你的IP</p>
</div>
<a href="/xiazai/skill10828" title="财经HTML高端海报生成" class="aritcle_card_btn flexRow flexcenter"><b></b><span>下载</span> </a>
</div>
</div> 提取段落时,<br> 不算新段落
<p></p> 是块级元素,浏览器会自动在前后加空行;而 <br> 只是换行符,不构成新段落。很多文本提取工具把每行 <br> 后的内容都当新段落切分,结果把一个自然段切成十几小段。
立即学习“前端免费学习笔记(深入)”;
使用场景:
从 CMS 导出内容、爬取新闻页、解析用户提交的富文本(含手动换行)
实操建议:
• 提取前先 normalize:把连续多个 <br> 替换为单个 <p></p> 分隔符,再统一用 <p></p> 切分
• 对不含 <p></p> 但含大量 <br> 的旧网页,可结合 CSS display: block 判定是否应视为段落容器
• 注意 <p></p> 缺失闭合标签的情况(如 <p>第一段</p>
<p>第二段</p>),现代解析器通常能自动补全,但需确认解析模式(如 BeautifulSoup 的 'html.parser' vs 'lxml')
标题与段落混合提取时,<h1></h1> 必须唯一且不可跳级
HTML 规范要求一个页面有且仅有一个 <h1></h1>(主标题),且标题层级不能跳跃(如 <h2></h2> 后直接出现 <h4></h4>)。但现实中大量网页违反该规范,导致提取后结构断裂或大纲错位。
性能影响:
跳级标题会让基于层级的 TOC 生成器(如 markdown-it-toc-done-right)漏掉中间层级,或强行插占位符破坏可读性
实操建议:
• 预处理阶段检测并修复跳级:遇到 <h4></h4> 但上一个标题是 <h2></h2> 时,插入虚拟 <h3></h3> 节点(仅内存中,不写回 HTML)
• 对无 <h1></h1> 的页面,提取第一个 <h2></h2> 并降级为 <h1></h1>(需标记为“推断主标题”)
• 使用 getElementsByTagName 或 CSS selector 时,避免用 'h1, h2, h3, h4, h5, h6' 简单拼接,应分别获取再 merge 排序,确保 DOM 顺序不被选择器引擎打乱
中文网页提取常忽略的编码与空格问题
很多中文 HTML 页面用 GBK 编码但未声明,或在 <p></p> 内混用全角空格、不间断空格( )、零宽空格(),导致提取后文本粘连或断句异常。
容易踩的坑:
• 用 requests.get(url).text 直接解析,未显式指定 encoding='gbk',中文变乱码
• 把 当普通空格处理,导致“标题 副标题”被切为两个词
• 忽略 <meta charset="utf-8"> 在 中的位置,误读成页面末尾的注释
实操建议:
• 先读取原始响应 bytes,用 chardet.detect() 判定编码,再 decode;或强制用 response.content.decode('gbk', errors='ignore')
• 提取文本后,统一 normalize 空格:re.sub(r'[\u00A0\u2000-\u200F\u2028\u2029\u202F\u2060\u3000]+', ' ', text)
• 对含大量内联样式(如 style="font-size:12px;")的标题,提取时剥离 style 属性,避免干扰语义判断
<div class="title"> 冒充 <code><h2></h2> 的 CMS 输出,或者用 <span></span> + CSS 实现的“伪段落”。这类情况必须结合 class 名、上下文位置、兄弟节点特征做二次判定,无法靠单一规则覆盖。


















