最近在处理一些数据,但是为了丰富数据,所以还需要从网上抓一些数据过来,起初是手动一点一点复制的,但是数据有点多,每一组数据手动处理的话,至少需要1个小时,20多组数据2天时间下不来,实在无法忍受枯燥的复制粘贴了,于是就想可不可以通过nodejs来抓取这些数据呢?
经过1个小时的研究,终于实现了想要的效果,感觉赚了一天的时间。
请求数据
这里我们请求数据使用axios,所以需要安装一下axios,然后使用axios去请求地址,获取我们想要的信息。
安装依赖
pnpm i axios
请求数据
const urlmove = '地址'
// 请求回来的promise对象数据
function req(url) {
return axios.get(url).then(function (data) {
// console.log(data)
return data
}).catch((error) => {
return false
})
}
处理数据
接下来就是处理数据了,当我们使用axios请求到数据后,就需要cheerio来对这些数据进行处理了,这里我请求的数据在网页的table标签中,所以需要处理table标签,我们只需要标签中特有的数据,所以要使用indexOf过一遍,看是不是需要的,是需要的再进行下一步。因为数据都在a标签内,所以还需要使用cheerio的find标签来获取a标签内的内容。
const $ = cheerio.load(data)
let list = []
$('table tbody tr td table tbody tr').each((index, el) => {
$(el).each((index2, el2) => {
console.log()
var datas = $(el2).html().indexOf('关键词') != -1
if (datas) {
var dataInfo = {
name: '',
code: '',
children: []
}
$(el2).find('a').each(function (index3, element) {
if (index3 == 0) {
dataInfo.name = $(element).text()
}
if (index3 == 1) {
dataInfo.code = $(element).text()
}
});
list.push(dataInfo)
}
})
})
循环抓取
数据需要三级数据,所以需要一个循环处理,为了避免对目标站点造成压力,这里我们设置一个延迟,每隔一段时间请求一次。
function sleep(n) {
var start = new Date().getTime();//定义起始时间的毫秒数
while (true) {
var time = new Date().getTime();//每次执行循环取得一次当前时间的毫秒数
if (time - start > n) {//如果当前时间的毫秒数减去起始时间的毫秒数大于给定的毫秒数,即结束循环
break;
}
}
}
保存数据
数据抓取完成后,我们需要保存数据,这里我们通过fs来将数据保存到指定的json文件中。
到这里一个nodejs 采集抓取数据的流程就走完了。
完整的实例代码
for (var i = 0; i < list.length; i++) {
var url = '网址' + list[i].code + '网址后缀/'
console.log('开始' + list[i].name)
list[i].children = await getErji(url)
sleep(5000);
for (var s = 0; s < list[i].children.length; s++) {
var url2 = '网址' + list[i].children[s].code + '网址后缀/'
list[i].children[s].children = await getErji(url2)
console.log(list[i].children[s].children)
sleep(5000);
}
}
const axios = require('axios')
const cheerio = require('cheerio')
const fs = require('fs')
// 需要引入的模块
var list = []
const urlmove = '地址'
// 请求回来的promise对象数据
function req(url) {
return axios.get(url).then(function (data) {
// console.log(data)
return data
}).catch((error) => {
return false
})
}
function sleep(n) {
var start = new Date().getTime();//定义起始时间的毫秒数
while (true) {
var time = new Date().getTime();//每次执行循环取得一次当前时间的毫秒数
if (time - start > n) {//如果当前时间的毫秒数减去起始时间的毫秒数大于给定的毫秒数,即结束循环
break;
}
}
}
// 获取主页nav内容的函数
async function getHome() {
const {data} = await req(urlmove)
const $ = cheerio.load(data)
let list = []
$('table tbody tr td table tbody tr').each((index, el) => {
$(el).each((index2, el2) => {
console.log()
var datas = $(el2).html().indexOf('关键词') != -1
if (datas) {
var dataInfo = {
name: '',
code: '',
children: []
}
$(el2).find('a').each(function (index3, element) {
if (index3 == 0) {
dataInfo.name = $(element).text()
}
if (index3 == 1) {
dataInfo.code = $(element).text()
}
});
list.push(dataInfo)
}
})
})
return list
}
// 获取二级数据
async function getErji(url) {
const {data} = await req(url)
const $ = cheerio.load(data)
let list = []
$('table tbody tr td table tbody tr').each((index, el) => {
$(el).each((index2, el2) => {
// console.log($(el2).html())
var datas = $(el2).html().indexOf('关键词查询') != -1 && $(el2).html().indexOf('全国') == -1
if (datas) {
var dataInfo = {
name: '',
code: '',
children: []
}
$(el2).find('a').each(function (index3, element) {
if (index3 == 0) {
dataInfo.name = $(element).text()
}
if (index3 == 1) {
dataInfo.code = $(element).text()
}
});
console.log(dataInfo)
list.push(dataInfo)
}
})
console.log(list)
})
return list
}
// 获取每一个导航的数据
async function main() {
// 一级数据
let list = await getHome()
console.log(list)
// return
sleep(3000);
// 二级数据
for (var i = 0; i < list.length; i++) {
var url = '网址' + list[i].code + '网址后缀/'
console.log('开始' + list[i].name)
list[i].children = await getErji(url)
sleep(5000);
for (var s = 0; s < list[i].children.length; s++) {
var url2 = '网址' + list[i].children[s].code + '网址后缀/'
list[i].children[s].children = await getErji(url2)
console.log(list[i].children[s].children)
sleep(5000);
}
}
console.log(list)
fs.writeFile('./data.json', JSON.stringify(list), function (err) {
if (err) {
return console.log("文件写入失败" + err.message)
}
console.log("文件写入成功")
})
}
//调用函数
main()