使用cheerio爬取Naver词典无法获取目标文本的解决方法
问题原因
- 目标页面是单页应用,URL中
#后的片段属于前端路由标识,不会随请求发送到服务端。你用axios直接请求该地址,拿到的只是页面初始的静态HTML骨架,不包含任何搜索结果相关的DOM节点。 - 页面上的「Word-Idiom」板块、所有词条内容都是浏览器加载完基础HTML后,执行JavaScript异步拉取数据动态渲染生成的。cheerio不具备浏览器的JS执行能力,只能解析静态返回的HTML内容,自然无法定位到动态生成的目标元素,拿不到对应文本。
解决方案
有两种可行实现方式,优先选择第一种:
方案1:直接调用站点后端数据接口(推荐)
这类动态站点的前端渲染数据都来自公开的后端接口,直接请求接口拿结构化数据,性能和稳定性远高于解析HTML:
- 用浏览器打开目标搜索页,按F12调出开发者工具,切换到网络面板,筛选Fetch/XHR类型请求
- 刷新页面触发搜索,在请求列表中找到返回词条、分类数据的接口(通常路径包含search关键字,返回格式为JSON)
- 直接用axios请求该接口,从返回的JSON数据中提取「Word-Idiom」对应内容即可。请求时注意携带和浏览器一致的请求头(如User-Agent、Referer),避免被服务端拦截。
方案2:使用无头浏览器渲染完整页面后解析
如果无法找到对应接口,可以用puppeteer、playwright这类无头浏览器工具,模拟真实浏览器环境访问页面,等JS执行完毕、动态内容全部渲染完成后,再提取HTML交给cheerio解析,示例代码:
先安装所需依赖:npm install puppeteer cheerio express
接口逻辑改写如下:
const puppeteer = require('puppeteer'); app.get("/conjugation", async (req, res) => { // 启动无头浏览器实例 const browser = await puppeteer.launch({ headless: "new" }); const page = await browser.newPage(); // 访问目标页面,等待网络请求空闲确保动态内容加载完成 await page.goto("https://en.dict.naver.com/#/search?query=%EC%B6%94%EC%9B%8C%EC%9A%94&range=all", { waitUntil: "networkidle2" }); // 等待目标元素渲染到页面上 await page.waitForSelector("#searchPage_entry > h3 > span.title_text.myScrollNavQuick.my_searchPage"); // 获取渲染完成的完整HTML内容 const htmlData = await page.content(); const $ = cheerio.load(htmlData); const targetText = $("#searchPage_entry > h3 > span.title_text.myScrollNavQuick.my_searchPage").text(); console.log(targetText); // 销毁浏览器实例 await browser.close(); res.send(targetText); });
- 该方案缺点是资源消耗高、响应速度慢,仅适合无公开接口的场景使用。
内容的提问来源于stack exchange,提问作者José Carlos
相关产品推荐
相关产品推荐

