0

0

如何使用 X-ray 解析非嵌套 HTML 结构为对象数组

花韻仙語

花韻仙語

发布时间:2026-02-04 11:26:08

|

993人浏览过

|

来源于php中文网

原创

如何使用 X-ray 解析非嵌套 HTML 结构为对象数组

x-ray 本身不支持直接抓取兄弟节点构成的逻辑区块,但可通过 jsdom 预处理 html,将散列的 `

` 及其后续同级内容动态包裹为独立容器,再用 x-ray 按标准父子结构解析,最终得到符合预期的 sections 数组。

在实际网页爬虫场景中,常遇到类似文档式 HTML:多个

标题平级排列,各自后跟可选的

副标题和
    列表,但无统一父容器分隔各节。这种“非嵌套、靠顺序语义组织”的结构,与 X-ray 基于 CSS 选择器树形遍历的设计范式天然冲突——它无法原生表达“以某个元素为起点,收集其后所有同级兄弟直到下一个同类元素”这样的逻辑。

    直接尝试 xray("h2", [...]) 会失败,因为 X-ray 会将每个

    作为独立上下文,而

      并不在其子树内;而 xray("article", [...]) 加数组语法,则只会执行一次迭代(因全文仅一个
      ),无法生成多节结果。

      核心思路:DOM 预处理 + X-ray 后解析
      借助 jsdom 构建内存 DOM,遍历所有

      ,将其及后续连续非-

      兄弟节点(如

        )动态包裹进新
        中。这样就把线性结构转化为多个具备明确父子关系的块级容器,X-ray 即可自然地对每个
        执行对象映射。

        以下是完整、健壮的实现方案(含错误处理与空值兼容):

        const { JSDOM } = require('jsdom');
        const xray = require('x-ray')();
        
        // 自定义 trim 过滤器(X-ray 默认不内置)
        xray.filters({
          trim: (value) => typeof value === 'string' ? value.trim() : value
        });
        
        async function parseNonNestedSections(html, url = '') {
          const dom = new JSDOM(html);
          const doc = dom.window.document;
        
          // 步骤1:定位所有 h2,并按逻辑分组包裹
          const h2s = doc.querySelectorAll('article h2'); // 限定在 article 内更安全
          if (h2s.length === 0) return { pageTitle: '', sections: [] };
        
          // 创建临时根容器,避免污染 body
          const wrapper = doc.createElement('div');
          wrapper.innerHTML = doc.querySelector('article').innerHTML;
        
          // 重置 wrapper 内部引用
          const h2List = wrapper.querySelectorAll('h2');
        
          for (let i = 0; i < h2List.length; i++) {
            const h2 = h2List[i];
            const sectionDiv = doc.createElement('section'); // 语义化标签更佳
        
            // 移动 h2 到新 section
            sectionDiv.appendChild(h2);
        
            // 收集后续同级节点,直到下一个 h2 或 null
            let next = h2.nextElementSibling;
            while (next && next.tagName !== 'H2') {
              const toMove = next;
              next = next.nextElementSibling;
              sectionDiv.appendChild(toMove);
            }
        
            // 插入到 wrapper 中原位置(保持顺序)
            h2.parentNode.insertBefore(sectionDiv, h2);
            h2.remove(); // 清理已移动的 h2
          }
        
          // 步骤2:用 X-ray 解析预处理后的 HTML
          const processedHtml = wrapper.innerHTML;
        
          return new Promise((resolve, reject) => {
            xray(processedHtml, {
              pageTitle: 'h1 | trim',
              sections: xray('section', [{
                subtitle: 'h3 | trim',
                elements: xray('ul li', ['| trim']) // 返回字符串数组,自动过滤空值
              }])
            })((err, result) => {
              if (err) return reject(err);
              // 确保 elements 始终为数组(即使 ul 不存在)
              result.sections = result.sections.map(sec => ({
                subtitle: sec.subtitle || undefined,
                elements: Array.isArray(sec.elements) ? sec.elements : []
              }));
              resolve(result);
            });
          });
        }
        
        // 使用示例
        const sampleHtml = `
          

        Page title

        Title 1

        Subtitle 1

        • Element 1
        • Element 2
        • Element 3

        Title 2

        Subtitle 2

        Title 3

        Subtitle 3

        • Element 1
        • Element 2
        • Element 3
        `; parseNonNestedSections(sampleHtml) .then(console.log) .catch(console.error);

        ? 关键注意事项:

        ARC Lab
        ARC Lab

        腾讯旗下ARC实验室推出的AI人像修复、抠图和增强工具

        下载

        立即学习前端免费学习笔记(深入)”;

        • 务必限定作用域:querySelectorAll('article h2') 而非全页 h2,避免误包其他区域标题;
        • 使用 section 替代 div:提升语义清晰度,且不影响 X-ray 解析;
        • 显式处理空值:subtitle 可能为 undefined(当某节无

          ),elements 统一归一化为 [];

        • ⚠️ 性能提示:对超大页面,频繁 DOM 操作可能有开销;若需高吞吐,建议切换至 Puppeteer 或 Cheerio + 手动遍历;
        • ? 扩展性友好:该模式可轻松适配

          +

          +

          等混合结构,只需调整 sectionDiv.appendChild(...) 的条件逻辑。

          此方案在保留 X-ray 声明式优势的同时,以最小侵入性补足了其对线性语义结构的解析短板,是生产环境中兼顾可读性、可维护性与可靠性的推荐实践。

相关文章

HTML速学教程(入门课程)
HTML速学教程(入门课程)

HTML怎么学习?HTML怎么入门?HTML在哪学?HTML怎么学才快?不用担心,这里为大家提供了HTML速学教程(入门课程),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
undefined是什么
undefined是什么

undefined是代表一个值或变量不存在或未定义的状态。它可以作为默认值来判断一个变量是否已经被赋值,也可以用于设置默认参数值。尽管在不同的编程语言中,undefined可能具有不同的含义和用法,但理解undefined的概念可以帮助我们更好地理解和编写程序。本专题为大家提供undefined相关的各种文章、以及下载和课程。

5452

2023.07.31

网页undefined是什么意思
网页undefined是什么意思

网页undefined是指页面出现了未知错误的意思,提示undefined一般是在开发网站的时候定义不正确或是转换不正确,或是找不到定义才会提示undefined未定义这个错误。想了解更多的相关内容,可以阅读本专题下面的文章。

3116

2024.08.14

网页undefined啥意思
网页undefined啥意思

本专题整合了undefined相关内容,阅读下面的文章了解更多详细内容。后续继续更新。

812

2025.12.25

DOM是什么意思
DOM是什么意思

dom的英文全称是documentobjectmodel,表示文件对象模型,是w3c组织推荐的处理可扩展置标语言的标准编程接口;dom是html文档的内存中对象表示,它提供了使用javascript与网页交互的方式。想了解更多的相关内容,可以阅读本专题下面的文章。

3471

2024.08.14

全国统一发票查询平台入口合集
全国统一发票查询平台入口合集

本专题整合了全国统一发票查询入口地址合集,阅读专题下面的文章了解更多详细入口。

37

2026.02.03

短剧入口地址汇总
短剧入口地址汇总

本专题整合了短剧app推荐平台,阅读专题下面的文章了解更多详细入口。

104

2026.02.03

植物大战僵尸版本入口地址汇总
植物大战僵尸版本入口地址汇总

本专题整合了植物大战僵尸版本入口地址汇总,前往文章中寻找想要的答案。

49

2026.02.03

c语言中/相关合集
c语言中/相关合集

本专题整合了c语言中/的用法、含义解释。阅读专题下面的文章了解更多详细内容。

9

2026.02.03

漫蛙漫画网页版入口与正版在线阅读 漫蛙MANWA官网访问专题
漫蛙漫画网页版入口与正版在线阅读 漫蛙MANWA官网访问专题

本专题围绕漫蛙漫画(Manwa / Manwa2)官网网页版入口进行整理,涵盖漫蛙漫画官方主页访问方式、网页版在线阅读入口、台版正版漫画浏览说明及基础使用指引,帮助用户快速进入漫蛙漫画官网,稳定在线阅读正版漫画内容,避免误入非官方页面。

76

2026.02.03

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Sass 教程
Sass 教程

共14课时 | 0.8万人学习

Bootstrap 5教程
Bootstrap 5教程

共46课时 | 3.2万人学习

CSS教程
CSS教程

共754课时 | 27.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号