使用Cheerio+request-promise爬取网站返回空数组,求排查问题
问题原因
- 锚点不会被服务器接收:你URL里的
#tab=buying&page_num=1是浏览器端的锚点标记,用request-promise发请求时,这部分不会被发送给服务器,服务器返回的只是页面的初始静态HTML,根本不是切换到"求购"标签后的内容。 - 内容靠前端JS动态生成:Buff的商品列表是页面加载后通过JavaScript动态渲染出来的,
cheerio只能解析静态的HTML代码,没法执行页面里的JS,所以自然找不到.card_csgo li这些动态生成的元素。而Chrome控制台能查到,是因为浏览器已经帮你执行完JS,渲染出了完整页面。
解决办法
办法1:用能执行JS的爬虫工具(比如Puppeteer)
Puppeteer可以模拟真实浏览器环境,执行页面JS,拿到渲染后的完整页面内容。示例代码:
const puppeteer = require('puppeteer'); const url = "https://buff.163.com/market/csgo#tab=buying&page_num=1"; const scrapeArr = []; async function scrape() { const browser = await puppeteer.launch(); const page = await browser.newPage(); // 等待页面加载完成,确保动态内容渲染完毕 await page.goto(url, { waitUntil: 'networkidle2' }); // 在浏览器环境里提取数据 const items = await page.evaluate(() => { const result = []; document.querySelectorAll(".card_csgo li").forEach(el => { const title = el.querySelector("h3").textContent.trim(); const link = el.querySelector("a").href; result.push({ title, link }); }); return result; }); scrapeArr.push(...items); console.log(scrapeArr); await browser.close(); } scrape();
办法2:直接调用官方API接口
打开Chrome开发者工具的Network面板,你会发现Buff的商品数据是通过API接口加载的。比如求购列表的接口大概是https://buff.163.com/api/market/goods/buying?game=csgo&page_num=1这类(具体可以自己抓包确认)。直接请求API比爬页面高效得多:
const request = require('request-promise'); const apiUrl = "https://buff.163.com/api/market/goods/buying?game=csgo&page_num=1"; async function scrape() { try { // 请求API并直接解析JSON响应 const res = await request.get({ url: apiUrl, json: true }); const scrapeArr = res.data.items.map(item => ({ title: item.name, link: `https://buff.163.com/goods/${item.id}` })); console.log(scrapeArr); } catch (err) { console.log(err); } } scrape();
内容的提问来源于stack exchange,提问作者risky last
相关产品推荐
相关产品推荐

