别再手动查电影了!用Node.js + 豆瓣API + 钉钉机器人做个新片推送助手
打造智能电影推送系统Node.js与豆瓣API的完美结合每次打开手机想找部好电影却总在各大平台间来回切换作为开发者我们完全可以用技术解决这个痛点。本文将带你构建一个自动化电影推送系统通过豆瓣API获取最新影片信息再结合钉钉机器人实现智能推送从此告别手动查片的烦恼。1. 系统架构设计这套推送助手的核心逻辑并不复杂定时获取数据→筛选处理→推送通知。但每个环节都有值得深入探讨的技术细节。系统工作流程定时触发任务如每天上午10点调用豆瓣API获取最新电影数据按预设条件过滤影片如评分7分的悬疑片格式化消息内容通过钉钉Webhook发送到指定群聊关键技术栈选择Node.js轻量高效的运行时环境Axios处理HTTP请求的最佳选择node-cron实现定时任务的利器钉钉机器人企业级消息推送通道提示开发前请确保已安装Node.js 14版本本文示例基于CommonJS模块系统2. 豆瓣API深度解析豆瓣开放API提供了丰富的电影数据接口我们需要重点关注以下两个// 正在热映电影 const IN_THEATERS_API https://api.douban.com/v2/movie/in_theaters // 即将上映电影 const COMING_SOON_API https://api.douban.com/v2/movie/coming_soon2.1 API参数详解这两个接口都支持以下关键参数参数名类型必填说明citystring否城市中文名如北京startnumber否起始索引默认为0countnumber否返回条数最大100典型请求示例const axios require(axios); async function fetchMovies() { const params { city: 上海, start: 0, count: 20 } try { const response await axios.get(IN_THEATERS_API, { params }); console.log(response.data.subjects); } catch (error) { console.error(API请求失败:, error.message); } }2.2 数据结构解析返回的影片数据包含丰富的信息字段这些是我们构建推送内容的基础{ title: 电影名称, original_title: 原片名, rating: { average: 7.5, max: 10, min: 0 }, genres: [剧情, 犯罪], casts: [ { name: 演员姓名, avatars: {small: 头像URL} } ], images: { small: 海报URL, large: 大图URL }, year: 2023 }3. 实现定时抓取任务定时任务是系统的核心调度机制我们使用node-cron库来实现。3.1 基础定时任务配置首先安装依赖npm install node-cron axios然后创建定时任务const cron require(node-cron); const { fetchMovies } require(./douban); // 每天上午10点执行 cron.schedule(0 10 * * *, () { console.log(开始执行电影数据抓取...); fetchMovies(); });3.2 高级定时策略实际应用中我们可能需要更复杂的调度策略分时段抓取白天密集抓取夜间减少频率错误重试API调用失败时自动重试节假日调整特殊日期调整抓取时间改进后的任务配置const schedule { normal: 0 10,14,18 * * *, weekend: 0 11,17 * * 6,0, holiday: 0 12 * * * }; function getSchedule() { const today new Date(); if (isHoliday(today)) return schedule.holiday; if (today.getDay() 0 || today.getDay() 6) return schedule.weekend; return schedule.normal; } cron.schedule(getSchedule(), fetchMoviesWithRetry(3));4. 数据筛选与处理获取原始数据后我们需要进行二次处理才能生成有价值的推送内容。4.1 筛选条件设计常见的筛选维度包括评分过滤只推送评分高于7分的电影类型偏好用户指定的电影类型上映时间即将上映或刚上映的影片演员/导演特定创作人员的作品示例筛选函数function filterMovies(movies, options {}) { return movies.filter(movie { const meetsRating movie.rating.average (options.minRating || 7); const meetsGenre !options.genres || movie.genres.some(genre options.genres.includes(genre)); return meetsRating meetsGenre; }); }4.2 消息内容格式化将原始数据转换为适合推送的富文本格式function formatMovieCard(movie) { return { title: ${movie.title} (${movie.year}), text: 评分: ${movie.rating.average}/10\n 类型: ${movie.genres.join(/)}\n 主演: ${movie.casts.slice(0,3).map(c c.name).join(、)}, image: movie.images.large, link: movie.alt }; }5. 钉钉机器人集成钉钉群机器人提供了简单易用的Webhook接口非常适合我们的推送场景。5.1 机器人创建步骤在钉钉群设置中添加自定义机器人设置机器人名称和头像选择自定义类型获取Webhook地址包含access_token5.2 消息推送实现钉钉支持多种消息类型我们使用最灵活的markdown格式const axios require(axios); async function sendDingTalkMessage(webhookUrl, content) { const data { msgtype: markdown, markdown: { title: 今日电影推荐, text: content } }; try { await axios.post(webhookUrl, data); } catch (error) { console.error(钉钉消息发送失败:, error.message); } }5.3 消息模板优化为了让推送内容更吸引人我们可以设计更丰富的消息模板** ${title} (${year})** ⭐ 评分: ${rating} 类型: ${genres} 主演: ${casts} [查看详情](${link}) 6. 系统部署与优化完成开发后我们需要考虑如何让系统稳定运行。6.1 日志记录完善的日志系统有助于问题排查const fs require(fs); const path require(path); function log(message) { const timestamp new Date().toISOString(); const logMessage [${timestamp}] ${message}\n; fs.appendFileSync( path.join(__dirname, app.log), logMessage ); }6.2 错误处理机制健壮的错误处理保证系统持续运行process.on(unhandledRejection, (reason, promise) { log(未处理的Promise拒绝: ${reason}); }); process.on(uncaughtException, (error) { log(未捕获的异常: ${error.stack}); process.exit(1); });6.3 性能优化建议随着数据量增长可以考虑以下优化缓存机制减少重复API调用批量处理合并多个请求并行处理利用Promise.all加速数据获取async function fetchAllData() { const [inTheaters, comingSoon] await Promise.all([ fetchMovies(IN_THEATERS_API), fetchMovies(COMING_SOON_API) ]); return [...inTheaters, ...comingSoon]; }7. 扩展功能思路基础功能实现后还可以考虑以下增强功能个性化推荐引擎基于用户历史偏好推荐协同过滤算法实现智能推荐多平台支持企业微信机器人集成Slack通知支持邮件推送备选方案用户交互功能通过回复消息收藏电影评分反馈改进推荐算法// 简单的用户偏好存储 const userPreferences { user1: { genres: [科幻, 动作], minRating: 8 } };实际部署时发现钉钉机器人对消息频率有限制约20条/分钟需要合理控制推送节奏。建议将高频更新改为每日精选推荐反而能获得更好的用户体验。