You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.15 01:23:30