node 爬取页面数据

使用 node 开发时难免会爬取一些数据资料,不可避免就需要一些爬虫功能,主要使用的技术 node + express + cheerio + axios + writeFile + readFile,只是作为基本的演示记录,不涉及数据库的存储等操作,通过读取文件代替。

  1. node 环境搭建;
  2. 创建项目文件夹 并初始化 package.json; npm init -y (-y 设置默认信息)
  3. 安装 express npm install express;
  4. 安装 axios npm install axios
  5. 安装 cheerio npm install cheerio

入口文件

// index.js
const express = require('express')
const axios = require('axios')
const cheerio = require('cheerio')

const writeFile = require('./writeFile')
const readFile = require('./readFile')
const { splitNextId } = require('./utils')
const { PORT, TRY_NUM } = require('./config')

const app = express()



let currentId = '5708267';
let isEnd = false;
let errId = "";
let errNum = 0;



app.get('/', (req, res) => {

  res.send('Hello World!')
  
})

app.listen(PORT, () => {
  console.log(`Example app listening on port ${PORT}`)
  // 获取数据,可以写在路由中通过接口形式调用
  getData(currentId)
  
})

function getData(id) {  
  axios.get(`https://www.xxx.com.cn/xxx/xxx/${id}.html`).then(async data => {
    
    const $ = await cheerio.load(data.data);
    const OContent = $('article');
    const OTitle = $('header');
    const OId = $('.nr_page>.dise:nth-of-type(3)').attr('href');

    const newId = splitNextId(OId)

    const title = OTitle.text().trim();
    const content = OContent.text().trim();
    if(!content || newId === '') {
      isEnd = true;
      console.log('数据爬取结束')
      return false;
    }
    const msg = `<div>当前是: ${title}, Id 是: ${currentId} ,下一章节ID是: ${newId}</div>`
    
    let val = msg + content;

    const oldFile = await readFile();
    await writeFile(currentId, oldFile + val);
    if(isEnd) {
      await getData(newId)
      currentId = newId;
    } else {
      console.log('数据爬取结束')
    }
    
   
  }).catch((err) => {
    if(errId == id) {
      errNum += 1;
    } else {
      errNum = 0;
      errId = id
    }

    if(errNum < TRY_NUM) {
      getData(id)
    } else {
      isEnd = true;
      console.log(`重连已超过${TRY_NUM}次自动停止`)
    }
  })
}

读取文件

// readFile.js
const fs = require('fs');
const { FILE_URL } = require('./config');
/**
* fileUrl写入的文件地址
*/
module.exports = function readFile(fileUrl) {
  return new Promise((resolve, reject) => {
    fs.readFile(fileUrl || FILE_URL, (err, data) => {
      if(err) {
        resolve('')
      }
      resolve(data.toString()) 
    })
  })
  
}

写入文件

// writeFile.js
const fs = require('fs');
const { FILE_URL } = require('./config');
/**
* currentId: 当前写入的信息id
* text:写入的内容
* fileUrl写入的文件地址
*/
module.exports = function writeFile(currentId, text, fileUrl) {
  return new Promise((resolve, reject) => {
    fs.writeFile(fileUrl || FILE_URL, text, error => {
      if(error) {
        throw new Error('新增失败')
      } else {
        console.log(currentId, '新增成功...')
        resolve(true)
      }
    })
  })
}

工具类函数

// utils.js
function splitNextId(url) {
  try {
    const arr = url.split('/');
    const [ id ] = arr.at(-1).split('.')
    return id;
  } catch (error) {
    return '';
  }
}

module.exports = {
  splitNextId
}

通过 nodemon index.js 运行即可,如果未安装 nodemon 也可通过 node index.js 运行。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值