0


记录一次Node.js编写爬虫的经历

在当今数字化的时代,数据的获取和管理变得越来越重要。本文将介绍如何使用 Node.js 实现从学院官网获取图片和新闻标题,并将其存储到 MySQL 数据库中。(如果你不想使用MySQL的话,后文有关于单独不储存到MYSQL数据库的详细说明)

一、背景与目标

    我们的目标是从学院官网中提取所有的图片和特定板块的新闻标题,然后将这些数据保存到 MySQL 数据库中,以便后续的分析和使用。通过这个过程,我们可以更好地了解学院的动态信息,同时也展示了 Node.js 在网络数据爬取和数据库操作方面的强大能力。

    页面如下 准备爬取该新闻的标题以及内容(包括图片)

    我的学校的新闻站点和图片

检查学校官网查看源代码,发现其ID选择器名称,这为后面的读取提供了极大便利。

二、技术栈

  1. Node.js:使用 Node.js 的https模块来发送 HTTP 请求,获取学院官网的页面内容。
  2. Cheerio:一个类似于 jQuery 的库,用于在服务器端解析 HTML 页面,方便提取所需的数据。
  3. MySQL:用于存储爬取到的新闻标题,通过mysql模块进行数据库连接和操作。

三、代码实现过程

** 首先,我们配置了项目所需的模块,包括https、cheerio、fs(文件系统模块)、path和mysql。我们还设置了学院官网的 URL 和一个用于存储下载图片的本地目录。
检查并创建download目录,如果该目录不存在。这个目录将用于存储从学院官网下载的图片。
配置 MySQL 连接,指定数据库的主机、用户名、密码和数据库名称。成功连接到数据库后,会在控制台打印相应的消息。
使用https.get方法发送 HTTP 请求到学院官网。在请求的响应中,我们收集页面的 HTML 内容。
使用 Cheerio 加载 HTML 内容,以便进行数据提取。**

** **请注意:
** **(1)在vscode中,,你需要引入cheerio库函数,该函数是Cheerio 就像是服务器端的 jQuery。它可以在 Node.js 环境中解析 HTML 文档,让你能够以类似于使用 jQuery 的方式来操作和提取 HTML 中的元素和数据。但是该函数支持的Node.js版本挺高,笔者在完成作业时发现自身的版本并不适合,所以需要下载高版本的Node.js(最好是最新的,以防止后期需要下载插件的时候不匹配)。
 **   (2)如果直接运行代码会发生错误,需要在vscode下载的插件的时候使用命令:npm install cheerio。或者在运行的中途报错如果缺少什么模块,公式同上:npm+install+模块。**

实现思路:

(1)提取所有图片地址:通过遍历页面中的标签,获取每个图片的src属性。如果src属性存在,将其转换为绝对地址,并添加到imgUrls数组中。
(2)下载图片:对于每个图片地址,使用https.get方法进行下载,并将图片保存到本地download目录中。下载过程中会在控制台打印相应的消息,以便了解下载进度。
(3)获取校园快讯标题和媒体白云标题:分别遍历特定 ID 的标签,提取新闻标题。使用.trim()方法去除潜在的空格,确保标题的整洁。然后,将标题插入到 MySQL 数据库中的相应表中。

** 代码如下:**

js:
const https = require('https');
const cheerio = require('cheerio');
const fs = require('fs');
const path = require('path');
const mysql = require('mysql');

// 要获取的网页 URL
const baseUrl = 'https://www.baiyunu.edu.cn/';
const basePath = path.join(__dirname, 'download');

// 检查并创建 download 目录如果不存在
if (!fs.existsSync(basePath)) {
  fs.mkdirSync(basePath, { recursive: true });
}

// 配置 MySQL 连接
const connection = mysql.createConnection({
  host: '127.0.0.1',//如果是本机,那同上
  user: 'root',
  password: 'xxxxxx',//根据自己的情况来
  database: 'xiaoyuantiqu'
});

connection.connect((err) => {
  if (err) {
    console.error('数据库连接错误:', err);
  } else {
    console.log('成功连接到 MySQL 数据库。');
  }
});

https.get(baseUrl, (res) => {
  let data = '';

  res.on('data', (chunk) => {
    data += chunk;
  });

  res.on('end', () => {
    const $ = cheerio.load(data);

    // 提取所有图片地址
    const imgUrls = [];
    $('img').each((index, element) => {
      let imgUrl = $(element).attr('src');
      // 处理相对地址
      if (imgUrl) {
        imgUrl = new URL(imgUrl, baseUrl).href;
        imgUrls.push(imgUrl);
      }
    });

    // 打印所有图片地址并下载图片
    imgUrls.forEach((imgUrl, index) => {
      console.log(imgUrl);
      downloadImg(imgUrl, index);
    });

    // 获取校园快讯标题并逐一插入数据库
    $('#message a').each((index, element) => {
      let title = $(element).text().trim(); // 使用.trim()去除潜在的空格
      insertNews('campus_news', title); // 插入校园新闻
    });

    // 获取媒体白云标题并逐一插入数据库
    $('#media a').each((index, element) => {
      let title = $(element).text().trim();
      insertNews('media_news', title); // 插入媒体新闻
    });
  });

}).on('error', (err) => {
  console.error(`请求错误: ${err.message}`);
});

function downloadImg(url, filename) {
  let ext = url.split('.').pop();
  filename += '.' + ext;
  console.log(`开始下载图片 ${filename}...`);
  https.get(url, (res) => {
    const file = fs.createWriteStream(path.join(basePath, filename));
    res.pipe(file);
    file.on('finish', () => {
      console.log(`图片 ${filename} 下载完成.`);
    });
  }).on('error', (err) => {
    console.error(`图片 ${filename} 下载失败: ${err.message}`);
  });
}

function insertNews(tableName, title) {
  connection.query(`INSERT INTO ${tableName} (title) VALUES (?)`, [title], (err) => {
    if (err) {
      console.error(`插入${tableName}标题错误:`, err);
    } else {
      console.log(`${tableName}标题已插入到数据库。`);
    }
  });
}

mysql:

CREATE DATABASE xiaoyuantiqu;

USE xiaoyuantiqu

     CREATE TABLE campus_news (
       id INT AUTO_INCREMENT PRIMARY KEY,
       title VARCHAR(1000) NOT NULL
     );

     CREATE TABLE media_news (
       id INT AUTO_INCREMENT PRIMARY KEY,
       title VARCHAR(1000) NOT NULL
     );

   //SELECT USER,HOST FROM mysql.`user`;
   //TRUNCATE TABLE campus_news;
   //TRUNCATE TABLE media_news;
运行结果:

方法二(不连接Mysql):

提前配置好Node.js环境,提前在路径上创建文件夹download(方便读取图片),记事本(读取所需标题并保存)。

代码如下:

const https = require('https');
const cheerio = require('cheerio');
const fs = require('fs');
const path = require('path');

// 要获取的网页 URL
const baseUrl = 'https://www.baiyunu.edu.cn/';
const basePath = path.join(__dirname, 'download');

// 检查并创建 download 目录如果不存在
if (!fs.existsSync(basePath)) {
  fs.mkdirSync(basePath, { recursive: true });
}

https.get(baseUrl, (res) => {
  let data = '';

  // 接收数据
  res.on('data', (chunk) => {
    data += chunk;
  });

  // 请求结束后处理数据
  res.on('end', () => {
    const $ = cheerio.load(data);

    // 提取所有图片地址
    const imgUrls = [];
    $('img').each((index, element) => {
      let imgUrl = $(element).attr('src');
      // 处理相对地址
      if (imgUrl) {
        imgUrl = new URL(imgUrl, baseUrl).href;
        imgUrls.push(imgUrl);
      }
    });

    // 打印所有图片地址并下载图片
    imgUrls.forEach((imgUrl, index) => {
      console.log(imgUrl);
      downloadImg(imgUrl, index);
    });

    // 获取校园快讯标题并写入记事本
    const newsTitles1 = $('#message').map((index, element) => $(element).text()).get();
    fs.writeFile('校园快讯.txt', newsTitles1.join('\n'), (err) => {
      if (err) {
        console.error('写入文件错误:', err);
      } else {
        console.log('校园快讯标题已写入 校园快讯.txt 文件。');
      }
    });

    // 获取媒体白云标题并写入记事本
    const newsTitles2 = $('#media').map((index, element) => $(element).text()).get();
    fs.writeFile('媒体白云.txt', newsTitles2.join('\n'), (err) => {
      if (err) {
        console.error('写入文件错误:', err);
      } else {
        console.log('媒体白云标题已写入 媒体白云.txt 文件。');
      }
    });
  });

}).on('error', (err) => {
  console.error(`请求错误: ${err.message}`);
});

function downloadImg(url, filename) {
  let ext = url.split('.').pop();
  filename += '.' + ext;
  console.log(`开始下载图片 ${filename}...`);
  https.get(url, (res) => {
    const file = fs.createWriteStream(path.join(basePath, filename));
    res.pipe(file);
    file.on('finish', () => {
      console.log(`图片 ${filename} 下载完成.`);
    });
  }).on('error', (err) => {
    console.error(`图片 ${filename} 下载失败: ${err.message}`);
  });
} 

如果不读取图片只是单纯读取标题

const axios = require('axios');
const fs = require('fs');

const url = "https://www.baiyunu.edu.cn/";

axios.get(url)
  .then(response => {
    const html = response.data;
    const cheerio = require('cheerio');
    const $ = cheerio.load(html);

    const titles = $('#message');

    let content = '';
    titles.each((index, element) => {
      content += $(element).text() + '\n';
    });

    // 写入到记事本文件
    fs.writeFileSync('校园快讯.txt', content);
  })
  .catch(error => {
    console.error('Error fetching data:', error);
  });
运行结果:

四、总结

    通过这段 Node.js 代码,我们成功地实现了从学院官网爬取图片和新闻标题,并将其存储到 MySQL 数据库中。这个过程展示了 Node.js 在网络数据爬取和数据库操作方面的灵活性和高效性。我们可以根据实际需求进一步扩展这个代码,比如添加错误处理机制、优化数据库插入操作等。希望这个示例能够为大家在 Node.js 数据爬取和数据库操作方面提供一些参考和启示。祝同学们学业进步,事事顺心!

本文转载自: https://blog.csdn.net/weixin_72949619/article/details/142672218
版权归原作者 热爱算法的小羊 所有, 如有侵权,请联系我们删除。

“记录一次Node.js编写爬虫的经历”的评论:

还没有评论