nodejs抓取动态网页(一个网络爬虫的开发过程及实现过程原理目标分析)

优采云 发布时间: 2021-10-14 22:14

  nodejs抓取动态网页(一个网络爬虫的开发过程及实现过程原理目标分析)

  Nodejs 将前端开发语言移植到了服务端。如今,前端开发者可以轻松地使用 Nodejs 实现网络爬虫,这在以前是不可想象的。本文介绍了一个简单的Nodejs爬虫开发过程,只想看代码拉到最后。

  爬行原理目标分析

  这次爬取的目标选择是观察cnBeta的新闻详情页收录到相邻页面的链接,但是通过查看源码发现这个链接是由Js生成的:

  

  这是一种常见的反爬虫措施。关联的页面链接通过异步请求获取,然后由js动态生成。检查网络面板,您可以看到该页面确实发送了一个异步请求。结果具有我们想要的关联页面 ID:

  

  接下来分析这个请求,可以发现有两个参数,这两个参数都可以在HTML中找到:

  

  第一个参数_csrf很容易直接在源码中搜索:

  

  第二个参数全文搜索找不到:

  

  观察这个参数的结构,发现数据被两个逗号分隔成三段,所以猜测数据是由于多部分拼接造成的,单独搜索真的找到了:

  

  但是只找到了最后两段数据,开头是1,不知道是哪来的。由于只有一个字符,检索起来比较困难,观察到这个请求在很多页面中都是以1开头的,所以这里干脆写死了。. .

  至此,对目标的分析结束,下面将执行爬虫。

  实施过程程序结构

  大体思路是从起始页开始爬取,异步获取上一个新闻页面的链接继续爬取,并设置最大爬取次数,防止陷入死循环。伪代码如下:

  1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

  let fetchLimit = 50; //最大抓取条数

let fetched = 0; //计数器

let getNext = function(_csrf, op){ //获取下一篇文章ID

return Promise(function(resolve,reject){

let nextID;

...

resolve(nextID);

})

}

let fetchPage = function(ID){ //抓取程序

let _csrf = ...;

let op = ...;

save(ID); //保存内容

fetched++; //计数器累加

getNext(_csrf, op).then(function(nextID) {

fetchPage(nextID); //获取下一篇ID并进入循环

});

}

fetchPage('STARTID'); //开始抓取

  功能点

  关键是保存内容。首先,获取页面的 HTML 代码。主要使用http模块,如下:

  1

2

3

4

5

6

7

8

9

10

11

  const http = require('http');

http.get(pageUrl, function(res){

let html='';

res.setEncoding('utf8');

res.on('data', (chunk) => {

html += chunk;

});

res.on('end', () => {

console.log(html); //这里得到完整的HTML字符串

});

})

  要从 HTML 获取信息,您可以使用常规匹配,或使用cheerio。Cheerio 可以说实现了一个 Nodejs 端的 jQuery。它和jQuery的区别在于它需要先生成一个实例,然后像jQuery一样使用它:

  1

2

3

  const cheerio = require('cheerio');

const $ = cheerio.load(html);

let news_title = $('.cnbeta-article .title h1').text().trim().replace(/\//g, '-');

  fs模块主要用于保存文件,如下:

  1

2

3

4

5

6

  const fs = require('fs');

fs.writeFile(FilePath, FileContent, 'utf-8', function(err) {

if (err) {

console.log(err);

}

});

  这里有个坑。我们希望将文章的文本保存为与标题同名的txt文本,但标题可能收录斜线(/)。保存这样的文件时,程序会误认为标题斜线之前的部分。把它看成是路径,报错,所以需要替换标题中的斜线。

  保存图片与保存文本大致相同。主要区别在于写入格式,需要以二进制方式写入:

  1

2

3

4

5

6

7

8

9

10

11

12

13

  http.get(img_src, function(res) {

let imgData = "";

res.setEncoding("binary"); //注意格式

res.on("data", function(chunk) {

imgData += chunk;

});

res.on("end", function() {

fs.writeFile(imgSavePath, imgData, "binary", function(err) { //注意格式

if (err) {

console.log(err);

}

});

});

  程序的结构和主要功能基本是这样的。

  后记

  实现爬虫说起来容易,但是健壮性真的很难保证。在爬cnBeta的过程中,又发现了一个301跳坑。URL跳转时,程序抓取的HTML为空,无法获取。因此,请求得到响应后,需要判断响应头是否为301,如果是,则需要从响应信息中找到重定向的URL,重新发起请求。好在cnBeta是不需要用户登录的,如果是必须登录才能访问的网站,爬虫会很麻烦。

  本项目完整代码见Nodejs爬虫,感谢cnBeta^^。

  前路原创技术文章,转载请注明出处:爬虫练习笔记/

  

  不甘平庸的你,快来和我一起充电,关注风景,获取更多精彩内容。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线