欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

【node】node.js实现一个简单的爬虫

程序员文章站 2022-03-16 11:11:44
...
前言

我们写项目的时候会需要模拟数据,这里教大家使用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搜索图书列表
【node】node.js实现一个简单的爬虫
得到目标网址

var url = 'http://search.dangdang.com/?key=js&act=input';

然后使用httpget模块去请求目标网页
data事件中数据会一节一节的下载

http.get(url,(res) => {
	res.on('data',(work) => {
		console.log(work)
	})
})

打印看一下效果,说明数据可以传输成功
【node】node.js实现一个简单的爬虫
等待数据下载完成,在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)			
	})
})

输出效果如下图,说明网页已经下载完成。但是很明显的出现了乱码,实际上是中文显示错误。
【node】node.js实现一个简单的爬虫
我们翻看网页源代码的头部,可以看到当当网的编码是GB2312,但是node只支持utf8/utf-8,所以就要用插件进行转化。
【node】node.js实现一个简单的爬虫
使用iconv-lite,修改过后的代码如下:

var data = Buffer.concat(ddw,length)   //
var html = iconv.decode(data,'GB2312').toString();
		 

打印一下html如下图,可以看到中文已经正常显示
【node】node.js实现一个简单的爬虫
接下来就是查看源代码,看我们需要提取的内容的DOM结构。如下图。查找好内容的格式之后就可以编写正则提取或者使用jquery操作。下面以jquery为例
【node】node.js实现一个简单的爬虫
不过node里面并不支持jquery,这里可以使用cheerio

cheeriojquery核心功能的一个快速灵活而又简洁的实现,主要是为了用在服务器端需要对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数组,效果如下。这样数据已经提取成功。

这里只是提取第一页,也可以添加参数提取更多页的内容,这里不再叙述。

【node】node.js实现一个简单的爬虫
下面将数据写入一个文件

fs.writeFileSync('./当当网.js',list)

打开当当网.js发现不显示内容。
【node】node.js实现一个简单的爬虫
别急,按如下方式写

fs.writeFileSync('./当当网.js',JSON.stringify(list,null,'\t'))

后面那个null是为了显示的时候换行

再次打开该文件,已经再次写入成功
【node】node.js实现一个简单的爬虫

完整代码


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爬取当当网数据的例子就完成啦

相关标签: node node.js