部署与调度Node.js爬虫:从本地执行到云端集成

部署与调度Node.js爬虫:从本地执行到云端集成

本教程详细指导如何部署和调度一个基于node.js的网页爬虫,使其能够每日自动运行并将其数据提供给前端应用。文章将区分客户端与服务器端javascript的运行环境,介绍本地任务调度方法,并探讨将爬虫集成到在线服务以实现数据共享的策略,同时涵盖数据持久化、cors处理及部署最佳实践。

1. 理解Node.js爬虫的运行环境

首先,我们需要明确一点:您所编写的爬虫代码(使用 puppeteer 和 fs 模块)是一个基于Node.js环境运行的服务器端脚本,而非在浏览器中执行的客户端JavaScript。

客户端JavaScript:在用户的浏览器中运行,主要负责页面交互、DOM操作等,无法直接访问本地文件系统或执行外部程序。服务器端Node.js:在服务器或本地计算机上运行,可以执行文件I/O操作(如 fs.writeFile),启动无头浏览器(如 puppeteer),处理网络请求等。

因此,要让您的 index.js 每日自动运行,并使其生成的数据可供前端页面访问,需要采取与部署静态网站不同的策略。

以下是您提供的Node.js爬虫代码示例:

const puppeteer = require('puppeteer');const fs = require('fs');// 爬取第一个数据源(async () => {  const browser = await puppeteer.launch();  const page = await browser.newPage();  await page.goto('https://br.advfn.com/investimentos/futuros/di-depositos-interfinanceiros/cotacoes',{    waitUntil: 'load',    timeout: 0  });  const textNode = await page.evaluate(()=>{    const nodeText = document.querySelector(".even.first").innerText;    const text = [nodeText];    return text  });  fs.writeFile('arreglo2.json', JSON.stringify(textNode), err =>{    if (err) throw new Error ('algo deu errado')      console.log('arreglo2.json saved successfully')  })  await browser.close(); // 关闭浏览器实例})();// 爬取第二个数据源(async () => {  const browser = await puppeteer.launch();  const page = await browser.newPage();  await page.goto('https://br.tradingview.com/symbols/TVC-DXY/',{    waitUntil: 'load',    timeout: 0  });  const textNode = await page.evaluate(()=>{    const nodeText = document.querySelector(".js-quote-ticker.tv-site-table__row.tv-widget-watch-list__row:nth-child(2)").children[1].children[1].children[0].innerHTML;    const text = [nodeText];    return text  });  fs.writeFile('arreglo.json', JSON.stringify(textNode), err =>{    if (err) throw new Error ('algo deu errado')      console.log('arreglo.json saved successfully')  })  await browser.close(); // 关闭浏览器实例})();// 爬取第三个数据源(async () => {  const browser = await puppeteer.launch();  const page = await browser.newPage();  await page.goto('https://br.advfn.com/bolsa-de-valores/fx/USDBRL/cotacao',{    waitUntil: 'load',    timeout: 0  });  const textNode = await page.evaluate(()=>{    const nodeText = document.querySelector(".qs-current-price").innerText;    const text = [nodeText];    return text  });  fs.writeFile('cotacaoFechamento.json', JSON.stringify(textNode), err =>{    if (err) throw new Error ('algo deu errado')      console.log('cotacaoFechamento.json saved successfully')  })  await browser.close(); // 关闭浏览器实例})();

请注意,为了避免资源泄露,在每个 puppeteer 实例使用完毕后,都应调用 await browser.close(); 关闭浏览器。

2. 本地调度方案:Windows任务计划程序

如果您希望爬虫在自己的Windows电脑上每日定时运行,最直接的方法是使用Windows任务计划程序(Task Scheduler)。

操作步骤:

打开任务计划程序: 在Windows搜索栏输入“任务计划程序”并打开。创建基本任务: 在右侧“操作”面板中选择“创建基本任务…”。任务命名与描述:名称: 例如 “每日爬虫任务”。描述: 简要说明任务用途。配置触发器:选择“每天”。设置起始日期和时间,例如每日“上午 8:00:00”。点击“下一步”。定义操作:选择“启动程序”。程序或脚本: 填写您的Node.js安装路径中的 node.exe。通常在 C:Program Filesnodejsnode.exe 或您自定义的安装路径。添加参数(可选): 填写您的爬虫脚本路径,例如 C:UsersYourUserpathtoyourprojectindex.js。请确保使用完整路径。起始于(可选): 填写您的爬虫脚本所在目录的路径,例如 C:UsersYourUserpathtoyourproject。这对于脚本中涉及相对路径的文件操作很重要。点击“下一步”。完成: 检查任务摘要,确认无误后点击“完成”。

现在,您的Node.js爬虫将在每天上午8点自动运行,并将数据保存到指定的JSON文件中。

3. 将爬虫数据集成到前端应用

爬虫在本地运行并生成JSON文件后,如何让您的静态HTML页面访问这些数据呢?这涉及到将数据“服务”出去。

3.1 本地开发环境的CORS问题

您提到在 C:// 目录下运行爬虫时遇到CORS错误,而在XAMPP环境下则正常。这是因为:

本地文件协议 (file://):当您直接在浏览器中打开HTML文件时,它使用 file:// 协议。出于安全考虑,浏览器严格限制 file:// 页面通过 XMLHttpRequest 或 fetch API 访问其他本地文件(即使是同一目录下的文件)。这被视为跨域请求,因此会触发CORS错误。HTTP服务器 (XAMPP):XAMPP提供了一个本地HTTP服务器。当您通过 http://localhost/your_project/index.html 访问页面时,它运行在 http:// 协议下。在这种情况下,HTML页面可以自由地请求同一域(localhost)下的其他资源(包括爬虫生成的JSON文件),因为它们不再是跨域请求。

因此,要让前端页面访问爬虫生成的数据,您需要一个HTTP服务器来提供这些JSON文件。

3.2 部署策略

a. 简单的Node.js HTTP服务器

您可以编写一个简单的Node.js服务器来提供爬虫生成的JSON文件。

创建 server.js 文件: 在您的项目根目录创建一个 server.js 文件。

const http = require('http');const fs = require('fs');const path = require('path');const hostname = '127.0.0.1'; // 或 '0.0.0.0' 允许外部访问const port = 3000;const dataDir = __dirname; // 假设JSON文件与server.js在同一目录const server = http.createServer((req, res) => {  // 允许跨域请求,重要!  res.setHeader('Access-Control-Allow-Origin', '*'); // 生产环境请指定具体域名  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS, PUT, PATCH, DELETE');  res.setHeader('Access-Control-Allow-Headers', 'X-Requested-With,content-type');  res.setHeader('Access-Control-Allow-Credentials', true);  // 处理OPTIONS请求(CORS预检请求)  if (req.method === 'OPTIONS') {    res.writeHead(204);    res.end();    return;  }  if (req.url === '/data/arreglo2.json') {    fs.readFile(path.join(dataDir, 'arreglo2.json'), (err, data) => {      if (err) {        res.statusCode = 404;        res.setHeader('Content-Type', 'text/plain');        res.end('File not found');        return;      }      res.statusCode = 200;      res.setHeader('Content-Type', 'application/json');      res.end(data);    });  } else if (req.url === '/data/arreglo.json') {     fs.readFile(path.join(dataDir, 'arreglo.json'), (err, data) => {      if (err) {        res.statusCode = 404;        res.setHeader('Content-Type', 'text/plain');        res.end('File not found');        return;      }      res.statusCode = 200;      res.setHeader('Content-Type', 'application/json');      res.end(data);    });  } else if (req.url === '/data/cotacaoFechamento.json') {     fs.readFile(path.join(dataDir, 'cotacaoFechamento.json'), (err, data) => {      if (err) {        res.statusCode = 404;        res.setHeader('Content-Type', 'text/plain');        res.end('File not found');        return;      }      res.statusCode = 200;      res.setHeader('Content-Type', 'application/json');      res.end(data);    });  } else {    res.statusCode = 404;    res.setHeader('Content-Type', 'text/plain');    res.end('Not Found');  }});server.listen(port, hostname, () => {  console.log(`Server running at http://${hostname}:${port}/`);});

运行服务器: 在终端中运行 node server.js。

前端获取数据: 您的HTML页面中的JavaScript可以通过 fetch API 请求数据:

fetch('http://127.0.0.1:3000/data/arreglo2.json')  .then(response => response.json())  .then(data => {    console.log('Fetched arreglo2.json:', data);    // 处理数据显示逻辑  })  .catch(error => console.error('Error fetching data:', error));

b. 云服务部署与调度

为了实现更稳定、可扩展的在线服务,您可以将爬虫部署到云平台。

Serverless 函数 (如AWS Lambda, Vercel Serverless Functions, Netlify Functions)优点:按需付费,无需管理服务器,可配置定时触发器(如AWS CloudWatch Events),非常适合定时运行的短任务。挑战:puppeteer 依赖无头浏览器,部署到Serverless环境需要额外配置(如使用 chrome-aws-lambda)。文件系统通常是临时的,JSON数据需要保存到持久化存储(如AWS S3、数据库)。PaaS 平台 (如Heroku, Render, Railway)优点:简化部署流程,支持Node.js应用,可配置定时任务(通常通过平台提供的附加组件或自定义脚本)。部署:您可以将爬虫和上述的Node.js HTTP服务器一起部署为一个应用。挑战:免费层级可能有限制,文件系统通常也是临时的,需考虑数据持久化。虚拟机/容器 (如AWS EC2, Docker, Kubernetes)优点:完全控制运行环境,可以安装所有依赖,适用于复杂或资源密集型爬虫。部署:您可以在虚拟机上安装Node.js,并将爬虫和HTTP服务器部署上去。调度可以使用Linux的 cron 任务或Windows的任务计划程序。挑战:管理成本较高,需要一定的DevOps知识。

数据持久化考量:在云环境中,服务器的文件系统通常是临时的。这意味着每次应用重启或Serverless函数调用时,之前保存的JSON文件可能会丢失。为了确保数据持久性,您应该考虑将爬取到的数据存储到:

云存储服务:如AWS S3、Google Cloud Storage。数据库:如MongoDB、PostgreSQL、MySQL。Redis:作为缓存或临时存储。

4. 关键注意事项与最佳实践

错误处理与日志:对于自动化任务,完善的错误处理和日志记录至关重要。当爬虫失败时,您需要知道原因并及时收到通知。环境配置:使用环境变量来管理端口号、数据存储路径、API密钥等配置信息,避免硬编码。CORS策略:如果您部署了自定义的Node.js HTTP服务器,请务必正确配置 Access-Control-Allow-Origin 头,以允许您的前端域名访问数据。在生产环境中,不要使用 *,而应指定具体的前端域名。资源管理:puppeteer 启动无头浏览器会消耗大量内存和CPU。确保您的服务器或云函数有足够的资源。在每次爬取任务完成后,务必调用 browser.close() 释放资源。部署自动化:随着项目迭代,手动部署会变得繁琐。考虑使用CI/CD工具(如GitHub Actions, GitLab CI/CD)自动化代码测试、构建和部署过程。爬虫道德与法律:在进行网页爬取时,请务必遵守目标网站的 robots.txt 协议,尊重网站的使用条款,并注意数据隐私和版权问题。避免对网站造成过大负载。

总结

部署和调度一个Node.js网页爬虫需要您理解其服务器端运行的特性。对于本地运行,Windows任务计划程序是一个简单有效的调度工具。而要将数据提供给在线前端应用,您需要一个HTTP服务器来提供这些JSON文件。根据您的需求和技术栈,可以选择部署简单的Node.js HTTP服务器,或利用云平台的Serverless函数、PaaS服务等更专业的解决方案。在任何部署中,数据持久化、错误处理和CORS配置都是不可忽视的关键点。

以上就是部署与调度Node.js爬虫:从本地执行到云端集成的详细内容,更多请关注创想鸟其它相关文章!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1598031.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2025年12月23日 12:34:35
下一篇 2025年12月23日 12:35:01

相关推荐

  • Ionic/Angular框架中:host CSS样式有效覆盖指南

    本文旨在提供在ionic和angular应用中有效覆盖`:host` css样式的详细指南。我们将探讨css层叠与特异性原理,并介绍如何通过调整样式顺序、利用父选择器以及在必要时使用`!important`规则来成功修改组件的宿主样式,确保您的自定义样式能够正确生效。 理解:host选择器与样式作用…

    好文分享 2025年12月23日
    000
  • HTML5模板标签怎么用_HTML5template标签实现内容模板的方法

    答案:HTML5的标签用于定义不渲染的HTML模板,通过JavaScript克隆其content属性可动态插入DOM,具有性能好、结构清晰、易于维护等优势,适用于列表、卡片、模态框等动态内容场景。 HTML5 的 标签是一个非常实用的功能,用于定义页面中暂时不渲染的 HTML 模板内容。这些内容可以…

    2025年12月23日
    000
  • HTML表单action怎么设置_HTML表单提交目标地址action属性用法

    HTML表单的action属性指定数据提交的URL,可设为相对路径、绝对路径或留空;需与method配合使用,确保目标地址有效且服务器能处理,是实现用户交互的基础。 HTML表单中的 action 属性用于指定表单提交后,数据将被发送到哪个URL进行处理。这个URL可以是相对路径、绝对路径,也可以是…

    2025年12月23日
    000
  • Node.js中多字段多文件上传与MongoDB路径存储:Multer实践指南

    本教程详细讲解如何在node.js中使用multer处理html表单中的多字段文件上传,并将文件保存到服务器指定目录。核心内容包括multer配置,express路由集成,以及如何在控制器中正确获取上传文件信息并将其存储路径而非文件本身的数据存入mongodb,优化数据库性能和可维护性。 在现代We…

    2025年12月23日
    000
  • HTML/JavaScript表单验证与数学函数应用:库存管理系统实现指南

    本教程详细阐述了如何使用html和javascript构建一个简单的库存管理表单,实现项目数量求和、50的倍数验证以及库存余额计算。文章深入分析了常见问题,如dom元素选择器误用、javascript `return`语句执行机制和html id重复,并提供了优化后的代码示例及专业建议,旨在帮助开发…

    2025年12月23日
    000
  • 从HTML blob: URL下载视频:JavaScript实现指南与技术考量

    本教程详细阐述了如何使用javascript从html “ 标签的 `blob:` url下载视频。文章聚焦于两种主要情况:当 `blob:` url由 `url.createobjecturl` 生成时,可通过创建虚拟下载链接轻松实现;而对于基于 `mediasource` api的流媒体视频,…

    2025年12月23日
    000
  • CSS定位:实现子元素溢出滚动父容器的技巧

    本教程详细探讨了如何在Web开发中,使一个绝对定位的子元素能够溢出其具有滚动属性的父容器。文章通过分析常见的裁剪问题,并结合具体的HTML、CSS和JavaScript代码示例,演示了如何通过调整父容器的`position`和`overflow`属性,以及子元素的定位方式,实现元素在视觉上突破父容器…

    2025年12月23日
    000
  • 深入理解innerText与标签:布局信息对文本渲染的影响

    innertext 方法在处理包含 标签的元素时,需要依赖元素的布局信息来正确计算文本内容。当元素未被添加到文档对象模型(dom)中时,由于缺乏布局上下文,innertext 可能不会将 渲染为换行符。而 innerhtml 始终能正确设置元素的 html 内容。要使 innertext 正确反映 …

    2025年12月23日
    000
  • 使用CSS变量与JavaScript实现动态主题切换

    本教程详细介绍了如何利用CSS自定义属性(变量)和JavaScript实现网页的动态主题切换功能。文章摒弃了直接操作CSS规则的复杂方法,转而采用在HTML根元素上添加`data-theme`属性的策略,通过CSS选择器高效地应用不同主题样式。此外,还演示了如何结合`localStorage`实现用…

    2025年12月23日
    000
  • jQuery属性选择器实现轮播图自动播放功能

    本文将详细介绍如何利用jquery的属性选择器,结合`setinterval`函数,实现一个带有手动导航功能的轮播图的自动播放。核心在于正确地定位并模拟点击带有特定`data`属性值的“下一页”按钮,从而在用户不操作时也能实现幻灯片的平滑切换。 轮播图基础结构与手动导航 在构建交互式轮播图时,我们通…

    2025年12月23日
    000
  • 标题:macOS浏览器中无法样式化HTML Option元素的原因及替代方案

    本文探讨了在macOS系统上的浏览器(Chrome, Firefox, Safari)中无法直接使用CSS样式化HTML 元素的原因。由于历史原因,浏览器依赖平台UI组件渲染,这些组件对CSS样式的支持有限。虽然现代浏览器正朝着自渲染控件的方向发展,但平台差异依然存在。本文同时提供了一种使用Java…

    2025年12月23日
    000
  • am5charts 地图交互:实现国家点击事件与链接跳转

    本教程详细介绍了如何在 am5charts 地图中为国家多边形添加点击事件监听器,并根据点击的国家数据(如url)实现页面跳转。文章将涵盖图表初始化、数据绑定、事件监听的设置,以及如何正确从 `datacontext` 中获取自定义数据,确保地图交互功能按预期工作。 1. 引言 am5charts …

    2025年12月23日
    000
  • 如何实现CSS父元素内容溢出时自动扩展,同时保持最小高度

    本教程探讨了如何使用CSS在父元素内容溢出时使其自动扩展高度,同时在内容未溢出时保持设定的最小高度。通过将 `height` 属性替换为 `min-height`,可以有效解决父元素内容溢出不自适应的问题,实现灵活的布局管理。 在网页布局设计中,我们经常会遇到这样的需求:一个父容器需要有一个初始的最…

    2025年12月23日
    000
  • CSS技巧:精确控制HTML元素内容与::after伪元素之间的间距

    本文探讨了在css中使用`::after`伪元素时,如何解决html元素内容与伪元素内容之间因不一致的尾随空格导致的间距问题。通过在`::after`内容前添加一个空格并配合负外边距进行视觉调整,可以实现无论原始html内容是否存在尾随空格,伪元素都能保持一致且精确的间距,提升用户体验和代码的健壮性…

    2025年12月23日
    000
  • 使用JavaScript获取URL的HTML内容

    本文详细介绍了如何使用JavaScript的`fetch` API从指定的URL获取其HTML内容。教程涵盖了发起网络请求、处理响应、提取文本内容的核心步骤,并提供了基于`async/await`的示例代码。同时,重点强调了客户端JavaScript在获取外部资源时必须面对的跨域资源共享(CORS)…

    2025年12月23日
    000
  • Flexbox布局中四象限页面布局的滚动条与空间异常问题解析与解决方案

    本文深入探讨了在使用flexbox构建包含侧边栏的四象限布局时,出现意外滚动条和额外空白空间的问题。核心原因在于主内容区域宽度未明确定义以及图像高度设置不当。教程将详细分析导致问题的css属性,并提供一套优化的解决方案,通过精确设置主内容区的宽度和调整图像的缩放方式,确保布局的完美呈现,避免不必要的…

    2025年12月23日 好文分享
    000
  • CSS技巧:实现子元素跟随父元素宽度动态滑动效果

    本教程探讨如何利用css实现一个悬停效果,使子元素能够精确地滑动其父元素的完整宽度,无论父元素宽度如何动态变化。我们将详细解析 `transform: translatex()` 的百分比计算机制,并提供两种有效的css解决方案:结合 `left` 属性与 `transform`,或利用 `marg…

    2025年12月23日
    000
  • 如何在悬停时使子元素滑动父元素的完整宽度

    本教程详细介绍了如何在CSS中实现当鼠标悬停在父元素上时,子元素能够精确滑动父元素的完整宽度。文章通过两种主要方法——结合使用`left`和`transform: translateX`,以及利用`margin-left`和`translate`——解决了`transform: translateX…

    2025年12月23日
    000
  • AMP页面中实现CSS动画:渐变背景动画的实践指南

    本教程详细介绍了如何在AMP(Accelerated Mobile Pages)页面中实现CSS动画,特别是全屏渐变背景动画。针对AMP对body元素直接样式操作的限制,核心解决方案是引入一个全高div容器,并将动画样式应用于该容器,而非直接作用于body,从而确保动画在AMP环境中正常运行。 理解…

    2025年12月23日
    000
  • CSS纯样式表格行内容切换:利用复选框与相邻选择器实现可折叠表格

    本教程详细讲解如何使用纯css实现表格行的内容切换功能,特别关注在复杂表格布局中利用复选框和相邻兄弟选择器 (`~`) 的技巧与限制。我们将探讨在表格单元格内部放置复选框时可能遇到的挑战,并提供一种既能保持功能又能兼顾用户体验和可访问性的解决方案。 1. CSS相邻兄弟选择器(~)的工作原理 在深入…

    2025年12月23日
    000

发表回复

登录后才能评论
关注微信