nodejs抓取动态网页(利用Python/.NET语言实现一个糗事百科的爬虫)
优采云 发布时间: 2022-04-03 13:14nodejs抓取动态网页(利用Python/.NET语言实现一个糗事百科的爬虫)
1.前言分析
通常爬虫都是用 Python/.NET 语言实现的,但现在作为前端开发者,自然需要精通 NodeJS。下面我们用NodeJS语言来实现一个尴尬事百科的爬虫。此外,本文中使用的一些代码是 es6 语法。
实现爬虫所需的依赖库如下。
request:使用get或post获取网页源代码。Cheerio:解析网页源代码,获取需要的数据。
本文首先介绍爬虫所需的依赖库及其使用方法,然后利用这些依赖库来实现一个网络爬虫,用于网络爬虫百科。
2. 请求库
request 是一个轻量级的 http 库,非常强大且易于使用。可以用来实现Http请求,支持HTTP认证、自定义请求头等。下面介绍请求库中的部分功能。
安装请求模块如下:
npm install request
安装好请求后,就可以使用了。接下来,使用请求请求百度的网页。
const req = require('request');
req('http://www.baidu.com', (error, response, body) => {
if (!error && response.statusCode == 200) {
console.log(body)
}
})
未设置 options 参数时,请求方法默认为 get 请求。而且我喜欢使用请求对象的具体方法,使用如下:
req.get({
url: 'http://www.baidu.com'
},(err, res, body) => {
if (!err && res.statusCode == 200) {
console.log(body)
}
});
但是在很多情况下,直接请求一个URL获取的html源代码,往往并不能得到我们需要的信息。一般来说,需要考虑请求头和网页编码。
网页请求头的编码
下面介绍如何在请求时添加网页请求头并设置正确的编码。
req.get({
url : url,
headers: {
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/62.0.3202.94 Safari/537.36",
"Host" : "www.zhihu.com",
"Upgrade-Insecure-Requests" : "1"
},
encoding : 'utf-8'
}, (err, res, body)=>{
if(!err)
console.log(body);
})
设置options参数,添加headers属性设置请求头;添加 encoding 属性来设置网页的编码。需要注意的是,如果encoding:null,则get请求得到的内容是一个Buffer对象,即body是一个Buffer对象。
上述功能足以满足以下需求。
3.cheerio 库
Cheerio 是一个服务器端的 Jquery,因其轻量、快速和易于学习的特性而受到开发人员的喜爱。掌握了 Jquery 的基础知识之后,学习 Cheerio 库就很容易了。可以快速定位网页中的元素,其规则与jquery定位元素的方法相同;它还可以修改html中元素的内容,并以非常方便的形式获取它们的数据。下面主要介绍cheerio快速定位网页中的元素并获取其内容。
首先安装cheerio库
npm install cheerio
下面给出一段代码,然后代码说明cheerio库的用法。分析博客园的首页,然后提取每个页面中文章的标题。
首先,分析博客园的首页。如下所示:
分析完html源码,首先通过.post_item获取所有title,然后分析每个.post_item,并使用a.titlelnk匹配每个title的a标签。代码在下面实现。
const req = require('request');
const cheerio = require('cheerio');
req.get({
url: 'https://www.cnblogs.com/'
}, (err, res, body) => {
if (!err && res.statusCode == 200) {
let cnblogHtmlStr = body;
let $ = cheerio.load(cnblogHtmlStr);
$('.post_item').each((index, ele) => {
let title = $(ele).find('a.titlelnk');
let titleText = title.text();
let titletUrl = title.attr('href');
console.log(titleText, titletUrl);
});
}
});
当然,cheerio 库也支持链式调用,上面的代码也可以改写为:
let cnblogHtmlStr = body;
let $ = cheerio.load(cnblogHtmlStr);
let titles = $('.post_item').find('a.titlelnk');
titles.each((index, ele) => {
let titleText = $(ele).text();
let titletUrl = $(ele).attr('href');
console.log(titleText, titletUrl);
上面的代码很简单,不用文字重复了。下面总结了一些我认为比较重要的点。
使用find()方法得到的节点集A,如果将A集中的元素作为根节点定位其子节点并获取子元素的内容和属性,则需要执行$(A [i ]) 包装器,如上面的 $(ele) 。上面代码中使用$(ele),其实也可以使用$(this),但是由于我使用的是es6箭头函数,所以我在每个方法中更改了回调函数的this指针,所以我使用了$(ele ); Cheerio 库还支持链式调用,例如上面的 $('.post_item').find('a.titlelnk')。需要注意的是,cheerio 对象 A 调用了 find() 方法。如果 A 是一个集合,那么 A 集合中的每个子元素都会调用 find() 方法并放回一个结果组合。如果 A 调用 text(),那么 A' 中的每个子元素
最后,我总结了一些比较常用的方法。
first() last() children([selector]):这个方法和find类似,只是这个方法只搜索子节点,而find搜索整个后代节点。
4. 尴尬的百科全书爬虫
通过上面对request和cheerio类库的介绍,下面两个类库是用来爬取尴尬事百科的页面的。
1、在项目目录下新建httpHelper.js文件,通过url获取尴尬百科的源码。代码如下:
//爬虫
const req = require('request');
function getHtml(url){
return new Promise((resolve, reject) => {
req.get({
url : url,
headers: {
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
"Referer" : "https://www.qiushibaike.com/"
},
encoding : 'utf-8'
}, (err, res, body)=>{
if(err) reject(err);
else resolve(body);
})
});
}
exports.getHtml = getHtml;
2、在项目目录下,新建一个Splitter.js文件,分析糗事百科的网页代码,提取你需要的信息,通过改变id建立爬取不同页面数据的逻辑的网址。
const cheerio = require('cheerio');
const httpHelper = require('./httpHelper');
function getQBJok(htmlStr){
let $ = cheerio.load(htmlStr);
let jokList = $('#content-left').children('div');
let rst = [];
jokList.each((i, item)=>{
let node = $(item);
let titleNode = node.find('h2');
let title = titleNode ? titleNode.text().trim() : '匿名用户';
let content = node.find('.content span').text().trim();
let likeNumber = node.find('i[class=number]').text().trim();
rst.push({
title : title,
content : content,
likeNumber : likeNumber
});
});
return rst;
}
async function splider(index = 1){
let url = `https://www.qiushibaike.com/8hr/page/${index}/`;
let htmlStr = await httpHelper.getHtml(url);
let rst = getQBJok(htmlStr);
return rst;
}
splider(1);
在获取尴尬百科网页的信息时,首先在浏览器中分析源码,定位到需要的标签,然后提取标签的文字或属性值,从而完成网页的解析。
Spliter.js 文件的入口是 spliter 方法。首先根据传入方法的index索引,构造出糗大百科的url,然后得到url的网页源码,最后将得到的源码传入getQBJok方法进行分析。本文只分析每一个文字笑话的作者、内容和点赞数。
直接运行Slider.js文件,爬取第一页的笑话信息。然后可以改变slider方法的参数来爬取不同页面的信息。
在上面已有代码的基础上,使用koa和vue2.0搭建一个浏览文本的页面,效果如下:
源代码已经上传到github。下载链接: ;
项目的运行依赖节点v7.6.0或以上。首先从 Github 克隆整个项目。
git clone https://github.com/StartAction/SpliderQB.git
克隆后,进入项目目录并运行以下命令。
node app.js
5. 总结
通过实现一个完整的爬虫功能,可以加深对Node的理解,部分实现的语言使用es6语法,这样可以加快es6语法的学习进度。另外,在这个实现中,遇到了Node的异步控制知识。本文使用了 async 和 await 关键字,这也是我最喜欢的。但是,在 Node 中,有几种方法可以实现异步控制。关于具体的方法和原则,有时间再总结。