使用Cheerio和Axios爬取CoinMarketCap无数据的解决办法
解决CoinMarketCap网页爬取不到表格数据的问题
我尝试从CoinMarketCap网站爬取数据,使用Node.js的Cheerio和Axios库实现,代码如下:
const cheerio = require("cheerio") const axios = require("axios") const dataScrapper = () =>{ const config = { method:"get", url:"https://coinmarketcap.com/", } axios(config) .then((response) =>{ const $ = cheerio.load(response.data) const selector = "#__next > div > div.main-content > div.sc-1a736df3-0.PimrZ.cmc-body-wrapper > div > div:nth-child(1) > div.sc-f7a61dda-2.efhsPu > table > tbody > tr" console.log($.html()) $(selector).each((index,ele) =>{ console.log(ele) console.log(index) }) }).catch((error) =>{ console.log(error) }) } dataScrapper()
运行后无法获取目标表格行数据,输出不符合预期,该如何解决?
问题原因
- 动态内容渲染:CoinMarketCap的表格数据是通过JavaScript动态加载的,Axios请求仅能获取初始静态HTML,不包含渲染后的表格内容。
- 动态类名失效:你使用的选择器包含动态生成的类名(如
sc-f7a61dda-2、efhsPu),这类类名会随网站更新或部署变化,导致选择器无法匹配目标元素。
解决方法
方法1:使用Puppeteer处理动态渲染
Puppeteer可以模拟浏览器加载页面,等待JS渲染完成后再获取内容,完美适配动态网站:
- 安装依赖:
npm install puppeteer
- 修改后的代码:
const puppeteer = require('puppeteer'); const dataScrapper = async () => { const browser = await puppeteer.launch({ headless: 'new' }); const page = await browser.newPage(); // 等待页面加载完成,直到网络请求稳定 await page.goto('https://coinmarketcap.com/', { waitUntil: 'networkidle2' }); // 等待表格元素加载完成 await page.waitForSelector('table.cmc-table tbody tr'); // 获取渲染后的页面HTML const html = await page.content(); const cheerio = require('cheerio'); const $ = cheerio.load(html); // 使用基于稳定属性/类名的选择器 $('table.cmc-table tbody tr').each((index, ele) => { const rank = $(ele).find('[aria-label="Rank"]').text().trim(); const name = $(ele).find('.cmc-table__column-name--name').text().trim(); const price = $(ele).find('[aria-label="Price"]').text().trim(); console.log(`Rank: ${rank}, Name: ${name}, Price: ${price}`); }); await browser.close(); }; dataScrapper();
方法2:直接调用官方API(推荐)
CoinMarketCap提供官方API,直接请求数据比爬取页面更高效、稳定,仅需注册获取API Key:
const axios = require('axios'); const dataScrapper = async () => { try { const response = await axios.get('https://pro-api.coinmarketcap.com/v1/cryptocurrency/listings/latest', { headers: { 'X-CMC_PRO_API_KEY': 'YOUR_API_KEY' // 替换为你的API Key }, params: { start: '1', limit: '10', convert: 'USD' } }); response.data.data.forEach(coin => { console.log(`Rank: ${coin.cmc_rank}, Name: ${coin.name}, Price: $${coin.quote.USD.price.toFixed(2)}`); }); } catch (error) { console.error(error); } }; dataScrapper();
方法3:优化静态请求的选择器(仅适用于部分静态内容)
如果网站存在部分静态渲染的内容,可改用不依赖动态类名的选择器,比如基于元素属性或稳定类名:
// 替换原选择器为更稳定的版本 const selector = 'table[aria-label="Cryptocurrency prices by market cap"] tbody tr';
注意:这种方法仍可能因网站动态渲染逻辑变化失效,仅作为补充方案。
内容的提问来源于stack exchange,提问作者Abhishek Poddar
相关产品推荐
相关产品推荐

