如何将res.json返回的API数组渲染至DOM并在浏览器控制台查看?
问题解决:将Cheerio爬取数据渲染到DOM并在浏览器控制台查看
首先修正你代码里的异步数据填充问题:当前爬取逻辑是异步执行的,服务器启动后直接访问接口会返回空数组(因为爬取还没完成),先调整代码确保数据爬取完成后再响应请求:
const PORT = process.env.PORT || 8000; const express = require("express"); const axios = require("axios"); const cheerio = require("cheerio"); const app = express(); const webpages = [{ name: "ynet", address: "https://www.ynet.co.il/sport/worldsoccer", }] // 封装爬取逻辑为异步函数 async function scrapeArticles() { const articles = []; // 用Promise.all等待所有爬取请求完成 await Promise.all(webpages.map(async webpage => { try { const res = await axios.get(webpage.address); const html = res.data; const $ = cheerio.load(html); $('div.slotView', html).each(function () { const title = $(this).text().trim(); const url = $(this).find('a').attr("href"); const img = $(this).find('img').attr('src'); articles.push({ title, url: url ? `https://www.ynet.co.il${url}` : '', // 补全相对路径 img, source: webpage.name }); }); } catch (err) { console.log(err); } })); return articles; } // 预爬取并缓存数据 let cachedArticles = []; scrapeArticles().then(data => { cachedArticles = data; console.log(`爬取完成,共获取 ${cachedArticles.length} 篇文章`); }); // 提供API接口返回数据 app.get("/api/articles", (req, res) => { res.json(cachedArticles); }); app.listen(PORT, () => { console.log(`server running on PORT ${PORT}`); });
一、在浏览器控制台查看数据
有两种简单实现方式:
- 手动控制台请求:启动服务器后打开浏览器访问
http://localhost:8000,按F12打开控制台,输入以下代码执行:fetch('/api/articles') .then(res => res.json()) .then(data => { console.log('爬取的文章数据:', data); window.articles = data; // 存入全局变量,后续直接输入articles即可查看 }); - 自动打印的HTML页面:在index.js中添加根路径路由,返回内嵌脚本的HTML,自动打印数据:
访问app.get("/", (req, res) => { res.send(` <html> <body> <script> fetch('/api/articles') .then(res => res.json()) .then(data => { console.log('文章数据:', data); alert('数据已打印到控制台,请按F12查看'); }); </script> </body> </html> `); });http://localhost:8000后,浏览器会自动在控制台打印数据。
二、将数据渲染到DOM
方案1:后端模板渲染(使用EJS)
适合快速实现的场景:
- 安装EJS模板引擎:
npm install ejs - 在index.js中配置模板引擎:
app.set('view engine', 'ejs'); app.set('views', './views'); // 指定模板文件夹路径 - 在项目根目录创建
views文件夹,新建index.ejs模板文件:<!DOCTYPE html> <html> <head> <title>爬取的文章列表</title> <style> .article-card { border: 1px solid #ddd; padding: 12px; margin: 10px 0; border-radius: 4px; } .article-card img { max-width: 220px; height: auto; } </style> </head> <body> <h1>来自<%= articles[0]?.source %>的文章</h1> <div class="articles-container"> <% articles.forEach(article => { %> <div class="article-card"> <h3><%= article.title %></h3> <% if(article.img) { %> <img src="<%= article.img %>" alt="<%= article.title %>"> <% } %> <p><a href="<%= article.url %>" target="_blank">查看原文</a></p> </div> <% }) %> </div> </body> </html> - 修改根路径路由为模板渲染:
启动服务器后访问app.get("/", (req, res) => { res.render('index', { articles: cachedArticles }); });http://localhost:8000,即可看到渲染完成的文章列表。
方案2:前端静态页面渲染
适合前后端分离的场景:
- 在项目根目录创建
public文件夹,新建index.html文件:<!DOCTYPE html> <html> <head> <title>爬取的文章列表</title> <style> .article-card { border: 1px solid #ddd; padding: 12px; margin: 10px 0; border-radius: 4px; } .article-card img { max-width: 220px; height: auto; } </style> </head> <body> <h1>爬取的文章列表</h1> <div id="articles-container"></div> <script> // 请求后端API获取数据并渲染DOM fetch('/api/articles') .then(res => res.json()) .then(articles => { const container = document.getElementById('articles-container'); articles.forEach(article => { const card = document.createElement('div'); card.className = 'article-card'; card.innerHTML = ` <h3>${article.title}</h3> ${article.img ? `<img src="${article.img}" alt="${article.title}">` : ''} <p><a href="${article.url}" target="_blank">查看原文</a></p> <p>来源:${article.source}</p> `; container.appendChild(card); }); // 同时打印数据到控制台 console.log('文章数据:', articles); }) .catch(err => console.error('获取数据失败:', err)); </script> </body> </html> - 在index.js中添加静态文件托管:
启动服务器后访问app.use(express.static('public'));http://localhost:8000,即可看到渲染好的页面,同时控制台会打印出数据。
内容的提问来源于stack exchange,提问作者Yossi Asnafy
相关产品推荐
相关产品推荐

