0

0

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

霞舞

霞舞

发布时间:2025-11-22 11:44:28

|

246人浏览过

|

来源于php中文网

原创

部署与调度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)。

操作步骤:

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

现在,您的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文件。

PixVerse
PixVerse

PixVerse是一款强大的AI视频生成工具,可以轻松地将多种输入转化为令人惊叹的视频。

下载

3.2 部署策略

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

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

  1. 创建 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}/`);
    });
  2. 运行服务器: 在终端中运行 node server.js。

  3. 前端获取数据: 您的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配置都是不可忽视的关键点。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

WorkBuddy
WorkBuddy

腾讯云推出的AI原生桌面智能体工作台

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
mysql修改数据表名
mysql修改数据表名

MySQL修改数据表:1、首先查看数据库中所有的表,代码为:‘SHOW TABLES;’;2、修改表名,代码为:‘ALTER TABLE 旧表名 RENAME [TO] 新表名;’。php中文网还提供MySQL的相关下载、相关课程等内容,供大家免费下载使用。

686

2023.06.20

MySQL创建存储过程
MySQL创建存储过程

存储程序可以分为存储过程和函数,MySQL中创建存储过程和函数使用的语句分别为CREATE PROCEDURE和CREATE FUNCTION。使用CALL语句调用存储过程智能用输出变量返回值。函数可以从语句外调用(通过引用函数名),也能返回标量值。存储过程也可以调用其他存储过程。php中文网还提供MySQL创建存储过程的相关下载、相关课程等内容,供大家免费下载使用。

534

2023.06.21

mongodb和mysql的区别
mongodb和mysql的区别

mongodb和mysql的区别:1、数据模型;2、查询语言;3、扩展性和性能;4、可靠性。本专题为大家提供mongodb和mysql的区别的相关的文章、下载、课程内容,供大家免费下载体验。

287

2023.07.18

mysql密码忘了怎么查看
mysql密码忘了怎么查看

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql密码忘了怎么办呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

519

2023.07.19

mysql创建数据库
mysql创建数据库

MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS 应用软件之一。那么mysql怎么创建数据库呢?php中文网给大家带来了相关的教程以及文章,欢迎大家前来阅读学习。

267

2023.07.25

mysql默认事务隔离级别
mysql默认事务隔离级别

MySQL是一种广泛使用的关系型数据库管理系统,它支持事务处理。事务是一组数据库操作,它们作为一个逻辑单元被一起执行。为了保证事务的一致性和隔离性,MySQL提供了不同的事务隔离级别。php中文网给大家带来了相关的教程以及文章欢迎大家前来学习阅读。

392

2023.08.08

sqlserver和mysql区别
sqlserver和mysql区别

SQL Server和MySQL是两种广泛使用的关系型数据库管理系统。它们具有相似的功能和用途,但在某些方面存在一些显著的区别。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

542

2023.08.11

mysql忘记密码
mysql忘记密码

MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。那么忘记mysql密码我们该怎么解决呢?php中文网给大家带来了相关的教程以及其他关于mysql的文章,欢迎大家前来学习阅读。

668

2023.08.14

TypeScript类型系统进阶与大型前端项目实践
TypeScript类型系统进阶与大型前端项目实践

本专题围绕 TypeScript 在大型前端项目中的应用展开,深入讲解类型系统设计与工程化开发方法。内容包括泛型与高级类型、类型推断机制、声明文件编写、模块化结构设计以及代码规范管理。通过真实项目案例分析,帮助开发者构建类型安全、结构清晰、易维护的前端工程体系,提高团队协作效率与代码质量。

26

2026.03.13

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
MySQL 教程
MySQL 教程

共48课时 | 2.6万人学习

MySQL 初学入门(mosh老师)
MySQL 初学入门(mosh老师)

共3课时 | 0.3万人学习

简单聊聊mysql8与网络通信
简单聊聊mysql8与网络通信

共1课时 | 850人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号