一聚教程网:一个值得你收藏的教程网站

最新下载

热门教程

HTML表格怎么转数组_html表格DOM转JSON数组方法详解

时间:2026-07-19 11:03:48 编辑:袖梨 来源:一聚教程网

DOMDocument是PHP解析HTML表格最稳妥方案,但需预处理编码、包裹div、关闭空白符保留,并用XPath或childNodes获取th/td;colspan/rowspan需手动展开为稀疏矩阵以匹配人眼视图。

DOMDocument 是 PHP 里最稳妥的起点,但直接用它转数组容易漏掉 th、跳过空行、崩在 malformed HTML 上,也默认不处理 colspanrowspan。别急着写正则,先看这几个关键点。

DOMDocument 加载 HTML 时总报 Warning 或结果为空

根本原因是 loadHTML() 会自动补全不规范结构(比如缺 <html><body>),同时触发 libxml 的警告。这些警告不中断执行,但会让 $dom->getElementsByTagName('table') 找不到东西。

解决方法很简单:

  • @ 抑制警告(仅开发期临时用):@$dom->loadHTML($html)
  • 更可靠的是预处理:用 mb_convert_encoding($html, 'HTML-ENTITIES', 'UTF-8') 统一编码,再补一层 <div> 包裹,避免根节点冲突
  • 必须设置 $dom->preserveWhiteSpace = false,否则 nodeValue 会混入大量换行和空格

getElementsByTagName('td') 为什么拿不到 th

getElementsByTagName() 只认一个标签名,'td''th' 是分开的。硬写两次再合并,容易错位——尤其当某行是 <tr><th>A</th><td>B</td></tr> 这种混合结构时。

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

正确做法是用 XPath 或组合查询:

  • 推荐用 $row->getElementsByTagName('*'),再过滤 nodeName === 'td' || nodeName === 'th'
  • 或者改用 $row->childNodes 遍历所有子节点,判断 nodeType === XML_ELEMENT_NODEnodeName 匹配
  • 千万别用 getElementsByTagName(['td','th']) —— PHP 不支持数组参数,会直接报错

遇到 colspan="2" 就少一列?

原始 DOM 不做单元格“展开”,colspan="2"<td> 在数组里仍只占一个位置,但视觉上它横跨两列。如果目标是导出 CSV 或渲染对齐表格,这就导致列数错乱。

手动填充逻辑要满足两个前提:

  • 先算出最大列数(遍历首行所有 th/td,累加 colspan 值)
  • 对每个单元格,按其实际起始列索引 + colspan 向右填值,跳过已被占用的位置(用二维数组标记已写)
  • rowspan 同理,但需跨行维护“当前列占用状态”,比 colspan 多一层状态管理

简单场景下可跳过填充,只记录原始结构;真要导出,建议用现成逻辑如 getTableData() 函数(JS 端)或封装好的 PHP 类,自己实现容易在边界 case(如 rowspan 超出行数)崩溃。

要不要用正则代替 DOM?

别。正则解析 HTML 是反模式,哪怕只是提取表格。你看到的“能跑”的正则代码,基本都假设:

  • 标签全部小写、无属性、无嵌套、无注释、无 CDATA
  • <td></td> 在同一行,且中间没换行符
  • 没实体编码( )、没 JS 动态插入内容

一旦网页来自真实爬虫或 CMS 输出,这些假设立刻失效。DOM 解析慢一点,但稳定;正则快一点,但上线后第一张含 data-* 属性的表格就挂。

真正该省时间的地方,是提前剪裁 HTML:用 preg_match('/<table[^>]*?>.*?</table>/is', $html, $match) 先捞出 table 片段,再交给 DOMDocument,比整个页面解析快得多。

复杂点不在怎么取文本,而在怎么定义“一行一列”——colspanrowspan 让行列关系变成稀疏矩阵,而多数业务只要“人眼看到的表格形状”。这时候,宁可多花 20 行代码模拟渲染逻辑,也不要妥协成“能跑就行”的扁平数组。

热门栏目