温馨提示:本文章主要是我当笔记,本身我也是菜鸡,如有不对之处欢迎指正。
第一步:安装cheerio包
相信这个都比较简单,都不用我写了吧。为了防止出意外还是贴一下代码吧 介绍一下:这玩意儿其实我感觉就是用来解析网页dom信息的,想了解的话移步去官网吧。
npm i cheerio
第二步:安装aixos
这个大家都熟悉吧,这只是个http请求库而已,其实还有其他的,不一定非要用这个,我只是顺手写一下。
npm i axios
开始啦,这里主要是我自己想要获取对应的forge相关信息,以此为例吧。
其实这儿也算是爬虫啦,我想要获取游戏版本只能去网站爬才能拿到,这返回的是一个游戏版本数组。
/** 获取游戏版本 */
async function getMcVersion() {
//获取网站的返回的HTML
const response = await axios.get('https://files.minecraftforge.net/net/minecraftforge/forge');
// 利用cheerio解析response中data的HTML
let $ = cheerio.load(response.data)
// 我想要的信息在 元素类 li-version-list>nav-collapsible>li 下
let result = $('.li-version-list .nav-collapsible li')
//留一个数组存放所有游戏版本信息
let arr = []
//获取到所有元素节点循环
result.each((index, item) => {
//正则并得到想要的游戏版本 text()是获取节点中的文本信息
const mcVsersion = $(item).text().replace(/[ ]|[\r\n]/g, "")
arr.push({
mc: mcVsersion,
url: `https://files.minecraftforge.net/net/minecraftforge/forge/index_${mcVsersion}.html`
})
})
// 返回所有游戏版本信息,及相关网站
return arr
}
接着这个是解析函数是针对各种不同游戏版本获取的相应信息,这个其实你们不用管,这个只是针对我个人需求,写的函数。
function getForgeInfo(data) {
let $ = cheerio.load(data)
let versionDomeList = $('.download-list tbody tr')[0]
let obj = {}
$(versionDomeList).children().each((index, item) => {
if (index == 0) {
obj.version = $(item).text().replace(/[ ]|[\r\n]/g, "")
} else if (index == 1) {
obj.date = $(item).text().replace(/[ ]|[\r\n]/g, "")
} else {
const liList = $(item).children().children()
$(liList).each((index, sonItem) => {
$(sonItem).each((index, sonItemA) => {
const strList = $(sonItemA).children()
const name = $(strList[0]).text().replace(/[ ]|[\r\n]/g, "").toLowerCase()
obj[name] = {
name
}
let path;
path = $(strList[1]).attr('href')
if (!path) {
path = $(strList[0]).attr('href')
}
obj[name]['path'] = path.replace('https://maven.minecraftforge.net', 'https://maven.fastmirror.net/repositories/minecraft')
const hexWord = $(strList[2]).text().replace(/[ ]|[\r]/g, "")
hexWord.split('\n').forEach(keyText => {
if (keyText.indexOf('MD5') !== -1) {
obj[name]['md5'] = keyText.split('MD5:')[1]
} else if (keyText.indexOf('SHA1') !== -1) {
obj[name]['sha1'] = keyText.split('SHA1:')[1]
}
})
})
})
}
})
console.log('obj信息', obj)
return obj
}
发送请求获取对应的HTML信息,很简单吧,这个主要是在构键函数数组使用
async function getForgeHtml(url) {
let {data} = await axios.get(url)
return data
}
开启异步任务,最大并发数可由自己设置
/**
*
* @param {*} fnList 函数数组
* @param {*} max 最大并发数
* @param {*} taskName 任务名称
* @returns
*/
async function startRun(fnList = [], max = 5, taskName = '未命名') {
if (!fnList.length) return;
log(chalk.blue(`开始执行多个异步任务,最大并发数:${max}`))
/** 存储结果 */
const dataList = [];
const count = fnList.length;
// 开始事件
const startTime = new Date().getTime();
let current = 0;
// 任务执行函数
const asyncTask = async (index) => {
return new Promise(async (resolve) => {
try {
const fn = fnList[index]
if (!fn) return resolve()
const data = await fn()
dataList[index] = data
log(`${taskName} 任务进度 ${((++current / count) * 100).toFixed(2)}%`)
await asyncTask(index + max)
resolve()
} catch (error) {
console.log('错误:', error)
resolve()
}
})
};
const taskList = new Array(max).fill(0).map((_, index) => asyncTask(index))
// 通过Promise.all()同时发送多个请求
await Promise.all(taskList)
const cost = (new Date().getTime() - startTime) / 1000
log(chalk.green(`执行完成,最大并发数:${max},耗时:${cost}s`))
return dataList
}
最终结果:如下
(async () => {
const forgeFnList = (await getMcVersion()).map((item) => () => getForgeHtml(item.url));
const infoData = await startRun(forgeFnList, 5, '获取forge页面')
const forgeInformation = infoData.map(item => { return getForgeInfo(item) })
fs.writeFile('../ceshi.json', JSON.stringify(forgeInformation), err => {
if (err) throw err;
console.log('写入成功');
})
console.log('结果:', forgeInformation)
})()
获取后的结果信息会被写入ceshi.json文件中,下图就是json文件截图: