使用whatsapp-web.js调用API向WhatsApp推送动漫新闻的问题咨询
WhatsApp动漫资讯机器人实现方案
现有代码问题排查
你写的代码跑不通是几个硬伤导致的:
- 调用的接口是Anime News Network的单部动漫详情接口,不是最新资讯列表接口,且URL里的
id是未替换的占位符,根本拿不到有效返回 - 该接口返回格式为XML,你没有做格式解析,直接读取
animeDb.url不存在对应字段 MessageMedia.fromUrl('animeDb.url')传入的是固定字符串,不是读取变量的正确写法,就算前面数据返回正常这里也会报资源地址无效- 现有逻辑只有用户发送关键词才被动触发,要实现自动推送需要加定时任务逻辑,仅靠
message事件监听做不到主动推送
具体实现步骤
前置依赖安装
先在项目目录安装需要的依赖包,执行以下命令:
npm install axios fast-xml-parser node-cron
axios:用于发起接口请求fast-xml-parser:用于解析Anime News Network接口返回的XML格式数据node-cron:用于配置定时任务,实现固定频率拉取最新资讯、主动推送
接口选型建议
新手优先选Anime News Network的公开资讯接口,无需申请密钥、没有鉴权门槛,返回数据稳定;MyAnimeList官方API需要注册开发者账号申请Client ID,鉴权流程复杂,不适合刚上手的时候用。
可运行代码示例
以下代码包含两个功能:用户发送anime-news时被动返回最新5条资讯、每2小时自动给指定聊天推送最新资讯,注意替换代码里的推送目标ID为你自己的目标群/用户ID:
const { Client, MessageMedia } = require('whatsapp-web.js'); const axios = require('axios'); const { XMLParser } = require('fast-xml-parser'); const cron = require('node-cron'); const client = new Client(); // 初始化XML解析器 const parser = new XMLParser(); // 存储已经推送过的资讯ID,避免重复推送 const pushedNewsIds = new Set(); // 替换成你要主动推送的聊天ID列表 const pushTargetIds = ['xxxxxx@c.us', 'xxxxxx@g.us']; // 拉取最新动漫资讯的公共方法 async function getLatestAnimeNews(limit = 5) { try { // 调用ANN最新资讯接口 const res = await axios.get('https://cdn.animenewsnetwork.com/encyclopedia/api.xml?news', { timeout: 10000 }); // 解析XML为JS对象 const xmlData = parser.parse(res.data); const newsList = xmlData.ann.news || []; // 过滤掉已经推送过的资讯,返回指定条数 return newsList .filter(news => !pushedNewsIds.has(news.id)) .slice(0, limit) .map(news => { pushedNewsIds.add(news.id); return { id: news.id, title: news.title, summary: news.summary, cover: news.thumbnail?.href || '', url: news.link } }); } catch (err) { console.error('拉取动漫资讯失败:', err.message); return []; } } // 发送资讯到指定聊天的公共方法 async function sendNewsToChat(chatId, newsList) { if (newsList.length === 0) return; for (const news of newsList) { let messageText = `📰 ${news.title}\n\n${news.summary}\n详情地址:${news.url}`; // 有封面就先传封面再传文字,没有就直接发文字 if (news.cover) { try { const media = await MessageMedia.fromUrl(news.cover); await client.sendMessage(chatId, media, { caption: messageText }); } catch (e) { await client.sendMessage(chatId, messageText); } } else { await client.sendMessage(chatId, messageText); } // 加个间隔避免发太快被风控 await new Promise(resolve => setTimeout(resolve, 1000)); } } client.on('message', async message => { const content = message.body.trim(); if (content === "anime-news") { const latestNews = await getLatestAnimeNews(); await sendNewsToChat(message.from, latestNews); } }); // 定时任务:每2小时拉取一次最新资讯推送给所有目标 cron.schedule('0 */2 * * *', async () => { const latestNews = await getLatestAnimeNews(); for (const targetId of pushTargetIds) { await sendNewsToChat(targetId, latestNews); } }); client.initialize();
注意事项
- 主动推送不要给非好友/未保存的陌生号码发消息,非常容易触发WhatsApp风控导致账号被封
- 接口拉取频率不要设置得太高,建议最短间隔1小时,避免被接口方限流封禁IP
- 如果需要用MyAnimeList的API,等你把当前逻辑跑通之后,只需要替换
getLatestAnimeNews方法里的接口请求、字段解析逻辑即可,消息发送、定时推送的逻辑可以完全复用
内容的提问来源于stack exchange,提问作者Cicada Coder
相关产品推荐
相关产品推荐

