利用NodeJs进行简单数据采集(微爬虫)
一直听说爬虫爬虫的,认为很无聊,没去研究过。偶尔的一次机会接触了爬虫,还不错。本文学习如何用
nodeJs
来爬虫获取小说的内容(我觉得叫抓取页面数据更适合,毕竟不是正儿八经的爬虫).
目标: 采集《斗破苍穹》小说的所有章节目录及URL
一、环境搭建
编码环境 具体安装就不说了,网上一堆安装介绍
node
必不可少的环境npm
oryarn
我更喜欢yarn,故本文将采用yarn来安装模块,不了解的童鞋可以去官网了解学习下,和npm差不多- 终端工具,本文展示的是
iTerm2
二、搭建项目&安装必要模块
打开
终端
oriTerm
orcmd
, 创建项目文件夹crawler
,进入文件夹使用yarn
初始化一个项目
$ md crawler
$ cd crawler
$ yarn init -y
新建一个
index.js
文件用来项目入口编码
$ touch index.js
至此项目搭建完毕,此时项目目录为:
. ├── index.js └── package.json
三、安装所需模块
安装所需模块列表
$ yarn add superagent superagent-charset cheerio
安装完后,打开
package.json
看下:
{
"name": "crawler",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"dependencies": {
"cheerio": "^1.0.0-rc.3",
"superagent": "^5.0.5",
"superagent-charset": "^1.2.0"
}
}
四、开始编码
使用你喜欢的编辑器打开项目,因为喜欢,所以寡人使用
VS Code
,由Atom
转到VS Code
的黑粉。不扯了,打开index.js
编入如下代码:(解释直接写到注释中)
// 导入需要用到的模块包
// 导入需要用到的模块包
const cheerio = require('cheerio');
const superagent = require('superagent');
require('superagent-charset')(superagent);
// 这里采用异步的方式抓取
async function getList() {
// arr数组用来存放抓取到的数据
let arr = []
// 要抓取的页面url链接
let url = 'https://www.biquge5.com/0_84/'
// 使用superagent获取该页面的数据
// 具体的配置参数可以去官网查看 这里是方便使用async/awit,采用的同步调用方式
let result = await superagent.get(url).set({
"Connection": "keep-alive" // 不是必须,纯粹展示superagent可以配置
}).charset('gbk').buffer(true) // charset为目标页面的编码,可以审查元素中head标签中查看
// 使用cheerio将result转换为类似于jQuery的对象,如果会jq的话这里就很简单了
// 具体的配置参数可以去官网查看
let $ = cheerio.load(result.text, {
decodeEntities: false
})
// 分析dom结构,获取需要的数据,可以在目标网页上审查看元素的dom结构
// 看到没,和jq的语法一样
$('._chapter li a').each((index, element) => {
// 把想要的数据放入到arr数组中
arr.push({
id: index,
title: $(element).text(),
url: $(element).attr('href')
})
})
return arr
}
// 调用getList()获取所有小说目录及链接
async function main() {
let result = await getList() // 注意await必须用在async修饰的函数中
console.log(result)
}
// 调用主函数
main()
四、运行
打开终端
iTerm2
, 运行下列命令
$ node index.js
不出意外的话,终端中会打印出结果
$ node index.js
[ { id: 0,
title: '第一章 陨落的天才',
url: 'https://www.biquge5.com/0_84/65397.html' },
{ id: 1,
title: '第二章 斗气大陆',
url: 'https://www.biquge5.com/0_84/65398.html' },
{ id: 2,
title: '第三章 客人',
url: 'https://www.biquge5.com/0_84/65399.html' },
...
{ id: 98,
title: '第一百章 威胁',
url: 'https://www.biquge5.com/0_84/65495.html' },
{ id: 99,
title: '第一百零一章 潜力值的分级',
url: 'https://www.biquge5.com/0_84/65496.html' },
... 1560 more items ]
至此,采集列表完毕,数据采集完毕后你可以保存到数据库,也可以保存到本地文件系统中,node都有对应的模块包
mysql2
&fs
。
五、结语
其实,这样看数据采集不难,就是分析下目标页面的数据结构。难的是采集数据一般是大批量的操作,要注意
并发控制
和反爬虫机制
等。
六、最后的最后
抛出采集 mzitu 站点的图片,下载到项目
dist
文件夹(需要手动创建)
const cheerio = require('cheerio')
const superagent = require('superagent')
const request = require('request') // 注意要 yarn add request
const fs = require('fs') // 要 yarn add fs
require('superagent-charset')(superagent)
// 辅助类
class Util {
static downImg(opts = {}, path = '') {
return new Promise((resolve, reject) => {
request.get(opts).on('reponse', reponse => {
console.log('img type: ', response.headers['content-type']);
}).pipe(fs.createWriteStream(path)).on('error', e => {
resolve('')
}).on('finish', () => {
resolve('download completed')
}).on('close', () => {
})
})
}
}
async function getContent(url) {
let res = await superagent.get(url).set({
"Connection": 'keep-alive'
}).charset('utf-8').buffer(true)
let $ = cheerio.load(res.text, {
decodeEntities: false
})
return $;
}
async function main() {
let arr = [];
// 抓取的首页的图片
const url = 'https://www.mzitu.com/'
let $ = await getContent(url)
$('#pins li').each((index, element) => {
arr.push($(element).find('img').attr('data-original'))
})
console.log(arr);
for (let u of arr) {
let opts = {
url: u,
headers: {
'Referer': 'https://www.mzitu.com/'
}
}
let path = './dist/' + u.substring(u.lastIndexOf('/'))
let r1 = await Util.downImg(opts, path)
console.log(r1);
}
}
main()
项目目录结构
.
├── dist
├── index.js
├── mz.js
├── node_modules
├── package.json
└── yarn.lock
2 directories, 4 files
可以看到有很多重复的代码,其实我们可以提取到一个模块中,这里因为
懒癌
犯了就不提取了,有兴趣的就自己提取吧。
给 TeanWang 打赏