Node.js使用cheerio/jsdom调用getElementsByTagName报错如何解决
问题根源
你代码里有2个核心错误:
- 执行
cheerio.load(...).html()得到的document变量是纯HTML字符串,不是DOM对象,自然没有DOM相关的getElementsByTagName、createElement等方法 - 你已经初始化了JSDOM实例,但没有正确拿到JSDOM封装的document对象,而是直接调用了字符串类型的
document的方法,所以报类型错误
修复方案
你引入了cheerio和JSDOM两个HTML解析库,任选一种即可实现需求:
方案1:仅用cheerio实现(更轻量,无需JSDOM)
cheerio本身支持类jQuery的选择器,不需要额外引入jsdom就能提取标签:
const db = require("../config/database"); const axios = require('axios'); const cheerio = require('cheerio'); const apiKey = process.env.API_KEY; exports.ingest = async(req, res) => { try { const {url} = req.query; const response = await axios.get(url); if (response.status == 200){ const $ = cheerio.load(response.data, {decodeEntities: true}); // 选择所有标签 const allElements = $('*'); const ele = []; allElements.each((i, el) => { ele.push(el.tagName.toUpperCase()); }); console.log('所有标签列表:', ele); res.send('标签提取完成'); } else{ res.status(response.status).send(response.statusText); } } catch (err) { console.error('处理失败:', err); res.status(500).send('服务内部错误'); } };
方案2:用JSDOM实现(适配原生DOM API写法)
如果你要使用原生DOM的API,从JSDOM实例中正确获取document对象即可:
const db = require("../config/database"); const axios = require('axios'); const jsdom = require('jsdom'); const{JSDOM} = jsdom; const apiKey = process.env.API_KEY; exports.ingest = async(req, res) => { try { const {url} = req.query; const response = await axios.get(url); if (response.status == 200){ // 直接传原始HTML字符串给JSDOM即可,不需要预处理 const dom = new JSDOM(response.data); // 正确获取模拟的document对象 const document = dom.window.document; const t = document.getElementsByTagName("*"); const ele = []; for (var i = 0; i < t.length; i++) { ele.push(t[i].tagName); } console.log('所有标签列表:', ele); res.send('标签提取完成'); } else{ res.status(response.status).send(response.statusText); } } catch (err) { console.error('处理失败:', err); res.status(500).send('服务内部错误'); } };
补充说明
- 原代码没有异常捕获,axios请求失败、页面解析失败都会直接抛错导致服务崩溃,建议按上面的示例加上try/catch包裹异步逻辑
- 代码中axios的TS类型报错是类型声明文件不匹配导致的,不影响运行,可通过升级axios到最新版、安装
@types/axios依赖解决 - 如果不需要用到原生DOM API,只用cheerio就足够满足HTML解析需求,不需要额外引入jsdom减少依赖体积
内容的提问来源于stack exchange,提问作者Vincenzo
相关产品推荐
相关产品推荐

