Cheerio+Phantom页面抓取异常:无法获取预期DOM内容求助
解决Smogon页面抓取时Cheerio无法获取渲染后DOM的问题
这个页面是前端JS动态渲染的单页应用,初始HTML里只有"Loading..."占位内容,h1、title这类元素都是JS执行后才生成的。不管是Axios直接请求,还是Phantom没等页面完全渲染就取content,都会拿到未渲染的原始HTML,自然选不到目标元素。
下面是具体解决办法:
方法1:优化PhantomJS的等待逻辑
Phantom默认可能在页面初始加载完成后就返回,但SPA需要等JS执行、DOM渲染完毕。可以通过固定延迟或等待目标元素出现来解决:
const phantom = require('phantom'); const cheerio = require('cheerio'); (async function() { const instance = await phantom.create(); const page = await instance.createPage(); await page.open('https://www.smogon.com/dex/sm/pokemon/gengar/ou/'); // 两种等待方式选一种: // 方式A:固定延迟(简单,按需调整时长) await new Promise(resolve => setTimeout(resolve, 3000)); // 方式B:等待目标元素出现(更可靠,超时5秒) // await page.waitForSelector('h1', { timeout: 5000 }); const content = await page.property('content'); const $ = cheerio.load(content); console.log('标题:', $('title').text()); console.log('H1文本:', $('h1').text()); await instance.exit(); })();
方法2:换成更现代的无头浏览器Puppeteer
PhantomJS已经停止维护,Puppeteer基于Chrome/Chromium,对现代SPA支持更好,内置的等待API更完善:
const puppeteer = require('puppeteer'); const cheerio = require('cheerio'); (async function() { const browser = await puppeteer.launch(); const page = await browser.newPage(); await page.goto('https://www.smogon.com/dex/sm/pokemon/gengar/ou/', { waitUntil: 'networkidle2' // 等待网络空闲,确保JS加载执行完成 }); const content = await page.content(); const $ = cheerio.load(content); console.log('标题:', $('title').text()); console.log('H1文本:', $('h1').text()); await browser.close(); })();
补充:Axios为什么没用?
Axios只是发HTTP请求拿服务器返回的初始HTML,不会执行页面里的JS,根本拿不到动态渲染出来的内容。必须用无头浏览器模拟真实浏览器环境,等JS跑完再抓DOM。
内容的提问来源于stack exchange,提问作者Fenrisulfr.33
相关产品推荐
相关产品推荐

