【node】node.js实现一个简单的爬虫
前言
我们写项目的时候会需要模拟数据,这里教大家使用node去实现一个简单的爬虫,获取目标网站的数据资源。(末尾附完整代码)
思路
首先找到目标网页,爬取整个网页的html内容,查看网页源代码,找到需要爬取内容的DOM结构,根据正则或者使用jquery操作(cheerio)提取相应的内容,然后将结果写入文件。
一、准备
所需要的模块:
1、http
:网络通信
2、fs
:文件操作
3、cheerio
:操作DOM(jquery的node版)
npm i cheerio
4、iconv-lite
:解决网页编码问题
npm i iconv-lite
二、实现
首先引入前面的几个模块
const http = require('http');
const fs = require('fs');
const cheerio = require('cheerio')
const iconv = require('iconv-lite');
寻找目标网页(以当当网为例)
以关键词js
搜索图书列表
得到目标网址
var url = 'http://search.dangdang.com/?key=js&act=input';
然后使用http
的get
模块去请求目标网页
在data事件
中数据会一节一节的下载
http.get(url,(res) => {
res.on('data',(work) => {
console.log(work)
})
})
打印看一下效果,说明数据可以传输成功
等待数据下载完成,在end事件
中输出,并将数据字节转化成我们看得懂的字符串。
http.get(url,(res) => {
var ddw = [] //用于存储目标网页的字节码
var length = 0 //ddw的长度
res.on('data',(work) => {
ddw.push(work)
length += work.length
})
res.on('end',() => {
var data = Buffer.concat(ddw,length) //
var html = data.toString() //html 网页字节码转成字符串
console.log(html)
})
})
输出效果如下图,说明网页已经下载完成。但是很明显的出现了乱码,实际上是中文显示错误。
我们翻看网页源代码的头部,可以看到当当网的编码是GB2312
,但是node只支持utf8/utf-8
,所以就要用插件进行转化。
使用iconv-lite
,修改过后的代码如下:
var data = Buffer.concat(ddw,length) //
var html = iconv.decode(data,'GB2312').toString();
打印一下html如下图,可以看到中文已经正常显示
接下来就是查看源代码,看我们需要提取的内容的DOM结构。如下图。查找好内容的格式之后就可以编写正则提取或者使用jquery操作。下面以jquery为例
不过node里面并不支持jquery,这里可以使用cheerio
cheerio
是jquery核心功能
的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对DOM进行操作的地方
将参数html传入,即可使用jquery操作html的内容
var $ = cheerio.load(html)
按照具体内容的结构(这里提取书名
、价格
、作者
、出版社
、时间
)写相应的代码。将获得的内容以对象形式传入一个数组。
var list = []
$('.bigimg').find('li').each((index,item) => {
var liclass = 'line'+(index+1)
//这里每一条数据的li标签的class名为‘line1、line2、line3’以此类推
var name = '' //书名
var price = '' //价格
var author = '' //作者
var cbname = '' //出版社
var time = '' //出版时间
name = $('.'+liclass).find('.pic').attr('title')
price = $('.'+liclass).find('.search_now_price').text()
author = $('.'+liclass).find('.search_book_author').find('a').eq(0).text()
cbname = $('.'+liclass).find('.search_book_author').find('a').eq(1).text()
time = $('.'+liclass).find('.search_book_author').find('span').eq(1).text()
list.push({
name:name,
price:price,
author:author,
cbname:cbname,
time:time
})
})
打印list数组,效果如下。这样数据已经提取成功。
这里只是提取第一页,也可以添加参数提取更多页的内容,这里不再叙述。
下面将数据写入一个文件
fs.writeFileSync('./当当网.js',list)
打开当当网.js
发现不显示内容。
别急,按如下方式写
fs.writeFileSync('./当当网.js',JSON.stringify(list,null,'\t'))
后面那个null是为了显示的时候换行
再次打开该文件,已经再次写入成功
完整代码
const http = require('http');
const fs = require('fs');
const cheerio = require('cheerio')
const iconv = require('iconv-lite');
var url = 'http://search.dangdang.com/?key=js&act=input';
http.get(url, (res) => {
var ddw = []; //存储网页字节码
var length = 0 //网页字节码长度
res.on('data',(work) => {
ddw.push(work) //将一节一节的字节码work添加到ddw
length += work.length
})
res.on('end',(work) => {
var list = [] //存储提取的数据对象
var data = Buffer.concat(ddw,length) //开辟缓存区存储字节码
var html = iconv.decode(data,'GB2312'); //将网页的编码GB2312转成utf8
var $ = cheerio.load(html.toString()) //引入jquery操作网页内容
$('.bigimg').find('li').each((index,item) => {
var liclass = 'line'+(index+1) //每条数据的li标签的class名
var name = '' //书名
var price = '' //价格
var author = '' //作者
var cbname = '' //出版社
var time = '' //出版时间
name = $('.'+liclass).find('.pic').attr('title')
price = $('.'+liclass).find('.search_now_price').text()
author = $('.'+liclass).find('.search_book_author').find('a').eq(0).text()
cbname = $('.'+liclass).find('.search_book_author').find('a').eq(1).text()
time = $('.'+liclass).find('.search_book_author').find('span').eq(1).text()
list.push({
name:name,
price:price,
author:author,
cbname:cbname,
time:time
})
})
// console.log(list)
fs.writeFileSync('./当当网.js',JSON.stringify(list,null,'\t'))
})
})
结尾
这样一个简单的node爬取当当网数据的例子就完成啦
上一篇: STM32CubeMX系列|触摸屏