如何读取html_读取HTML文件内容或元素的技巧【指南】

13次阅读

fetch 读取本地 html 文件触发 CORS 错误是因 file:// 协议被浏览器禁止跨域请求,解决方法是部署到本地 http 服务或改用 xmlHttpRequest;domParser 解析 HTML 字符串更安全;node.js 中需用 fs 读取文件并注意编码与路径。

如何读取html_读取HTML文件内容或元素的技巧【指南】

fetch 读取本地 HTML 文件会触发 CORS 错误

浏览器直接用 fetch('./page.html') 加载本地 HTML 文件时,如果页面是通过 file:// 协议打开的,绝大多数现代浏览器会拒绝请求,并抛出类似 Blocked by CORS policy: Cross origin requests are only supported for protocol schemes: http, data, chrome, chrome-extension, https. 的错误。

这不是代码写错了,而是浏览器安全策略限制——file:// 协议不被视作合法的跨域请求源。解决方法只有两个:

  • 把页面部署到本地 HTTP 服务上(推荐),比如用 npx servepython3 -m http.server 或 VS Code 的 Live Server 插件
  • 改用 XMLHttpRequest 并设置 responseType = 'document'(仅限同源且非 file:// 场景)

别试图用 readAsText + FileReader 去读取用户选择的 HTML 文件——那只能用于 显式选取的场景,不适用于预设路径加载。

DOMParser 解析 HTML 字符串比 innerHTML 更安全可靠

当你拿到一段 HTML 字符串(比如从 fetch 返回的 text() 结果),想提取其中的 或某个 class="content" 元素,不要直接往 div.innerHTML 里塞再查——这会执行内联脚本、触发图片加载、污染当前页面 DOM。

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

DOMParser 是专为此设计的轻量级解析器,它生成的是独立文档对象,完全隔离:

const parser = new DOMParser(); const doc = parser.parseFromString(htmlString, 'text/html'); const title = doc.querySelector('title')?.textContent; const mainContent = doc.querySelector('.content')?.outerHTML;

注意两点:

  • MIME 类型必须写成 'text/html',写成 'application/xml' 或漏掉会导致解析失败或行为异常
  • doc 是完整文档,所以 querySelector 能直接匹配 下的元素,无需额外包裹

Node.js 环境下读取 HTML 文件要用 fs.readFileSyncfs.promises.readFile

node.js 里没有 fetch,也不能用 DOMParser(原生不支持),得靠第三方库补全 DOM 能力。但第一步永远是把文件内容读成字符串:

const fs = require('fs'); const html = fs.readFileSync('./index.html', 'utf8');

或者用 Promise 版本:

const { readFile } = require('fs').promises; const html = await readFile('./index.html', 'utf8');

常见坑:

  • 忘记传 'utf8' 编码参数,结果得到 Buffer,后续 parseFromString 会报错
  • 路径写相对路径却没注意工作目录(process.cwd()),建议用 path.resolve(__dirname, 'index.html') 定位

之后才能交给 jsdomcheerio 处理。例如 cheerio 的典型用法:

const $ = require('cheerio'); const html = fs.readFileSync('./index.html', 'utf8'); const $html = $.load(html); const title = $html('title').text();

cheerio 提取元素比原生 DOM API 更适合服务端批量处理

如果你在 Node.js 中要批量分析几十个 HTML 文件、提取标题、链接、元数据,cheerio 是更优选择:它模拟了 jquery API,语法简洁,不渲染、不执行 JS、内存占用低。

对比 jsdom

  • cheerio 没有 windowdocument 全局对象,不能运行脚本,但解析速度通常快 3–5 倍
  • cheerio.load() 返回的是“伪 DOM”,所有选择器操作都基于字符串分析,因此不支持 :has():nth-child(2n) 等复杂 css4 伪类(除非升级到 v1.0+ 并启用 xmlMode: false
  • 若 HTML 不规范(如自闭合标签写成 如何读取html_读取HTML文件内容或元素的技巧【指南】 而非 如何读取html_读取HTML文件内容或元素的技巧【指南】),cheerio 默认能容错,DOMParser严格模式下可能报错

一个真实场景示例:提取所有带 href 的外链,并排除站内路径:

const $ = require('cheerio'); const html = fs.readFileSync('page.html', 'utf8'); const $html = $.load(html); const externalLinks = []; $html('a[href]').each((i, el) => {   const href = $html(el).attr('href');   if (href && /^https?:///.test(href)) {     externalLinks.push(href);   } });

实际处理 HTML 时,最易被忽略的是编码识别——特别是老站点用 gbkbig5 编码却没声明 ,这时 fs.readFileSyncfetch 拿到的内容会乱码,后续所有解析都失效。遇到这类情况,得先用 iconv-liteencoding-sniffer 探测真实编码再转 UTF-8。

text=ZqhQzanResources