如何修改Heroku部署的Node.js爬虫,实现每X分钟自动更新JSON返回数据
问题根因
- 全局声明的
myarr数组没有在每次爬取前重置,每次请求都会把新抓取的数据追加到原有旧数据的末尾,所以接口永远会保留首次抓取的内容,看不到最新结果。 - 当前逻辑只有收到接口请求时才会触发爬取,无法实现自动定时更新的需求。
修改方案
分两种场景,你可以按需选择:
场景1:每次请求接口时实时抓取最新数据返回
只需要在每次触发爬取逻辑前,先清空myarr数组即可,修改后的代码如下:
const axios = require('axios'); const cheerio = require('cheerio'); const express = require('express'); const PORT = process.env.PORT || 8000; // 替换为你实际要爬的目标地址 const myUrl = '你的爬取目标链接'; const app = express(); app.get('/mylink', (req, res) =>{ // 每次爬取前清空数组,清除旧数据 const myarr= [] axios.get(myUrl,{ responseEncoding: 'binary' }) .then((response) => { const html = response.data const $ = cheerio.load(html) $('tr', html).each(function (parentIdx) { const title = $(this).find('a.tw-hidden.lg\:tw-flex.font-bold.tw-items-center.tw-justify-between').text() myarr.push({ title }) }) res.json(myarr) }).catch((err) => { console.log(err) res.status(500).json({error: '抓取失败'}) }) }) app.listen(PORT, () => console.log(`Server avviato ed in ascolto sulla PORTA ${PORT}`))
场景2:实现每X分钟后台自动更新,接口直接返回最新缓存数据
无需每次请求都触发爬取,后台定时爬取后存储最新结果,接口直接返回即可,响应速度更快,也能降低目标网站的访问压力。以下示例为每10分钟更新一次,你可以自行调整时间间隔:
const axios = require('axios'); const cheerio = require('cheerio'); const express = require('express'); const PORT = process.env.PORT || 8000; // 替换为你实际要爬的目标地址 const myUrl = '你的爬取目标链接'; // 定义更新间隔,单位为毫秒,示例为10分钟 const UPDATE_INTERVAL = 10 * 60 * 1000; const app = express(); // 存储最新爬取结果 let latestData = []; // 封装爬取逻辑 const fetchData = async () => { try { const response = await axios.get(myUrl,{ responseEncoding: 'binary' }) const html = response.data const $ = cheerio.load(html) const newArr = [] $('tr', html).each(function (parentIdx) { const title = $(this).find('a.tw-hidden.lg\:tw-flex.font-bold.tw-items-center.tw-justify-between').text() newArr.push({ title }) }) // 覆盖旧数据 latestData = newArr; console.log('数据更新完成') } catch (err) { console.log('抓取出错:', err) } } // 服务启动时先执行一次爬取 fetchData(); // 定时每X分钟更新一次数据 setInterval(fetchData, UPDATE_INTERVAL); app.get('/mylink', (req, res) =>{ // 直接返回最新缓存的结果 res.json(latestData) }) app.listen(PORT, () => console.log(`Server avviato ed in ascolto sulla PORTA ${PORT}`))
注意事项
- Heroku免费版本的应用如果30分钟没有收到外部请求会自动休眠,休眠后定时任务会停止,如果你需要保证定时任务持续运行,可以配置定期ping应用接口的服务避免休眠。
- 爬取第三方网站时请遵守目标网站的
robots.txt规则,合理控制爬取频率,避免触发反爬机制。
内容的提问来源于stack exchange,提问作者juniorDevFla
相关产品推荐
相关产品推荐

