资讯专栏INFORMATION COLUMN

用Promise实现队列(爬一爬慕课网HTML代码)

XFLY / 3374人阅读

摘要:项目初始化创建一个文件,快捷创建非常简单。基本使用方法具体的请自行点击连接查看哟页面数据解析是一个的库,可以理解为一个版本的,用来从网页中以取数据,使用方式和基本相同。执行数组中每个值的函数,包含四个参数作为第一次调用的第一个参数。

项目初始化

创建一个package.json文件,webstorm快捷创建package.json非常简单。
使用 npm init 快速创建。

工具模块

需要下载的的模块

superagent 页面数据下载

cheerio 页面数据解析

这是2个npm包,我们先下载:

npm install superagent cheerio --save

需要引入的模块

fs

path

引入项目依赖
const cheerio = require("cheerio");
const agent = require("superagent");
const path = require("path");
const fs = require("fs");
定义地址数组

我们希望以队列的形式逐个对这些地址进行访问,获取HTML代码,以便后续处理:

const urls = [{
    page:1,
    url:"https://www.imooc.com/course/list?c=fe&page=1"
},{
    page:2,
    url:"https://www.imooc.com/course/list?c=fe&page=2"
},{
    page:3,
    url:"https://www.imooc.com/course/list?c=fe&page=3"
}];
定义数据结构

慕课网课程列表:

对此我们定义如下的数据结构:

 [
     {
      page: 1,
      data: [
          {
             title:"", // 课程标题
             imgurl:"", // 课程图片
             level:"", // 等级
             studynum:0, // 学习人数
             description:"xxxx" // 课程描述
        }
        ...... // 每一个页面有多条课程信息
      ]  
    }
    ...... // 一共有多个页面
 ]
superagent 页面数据下载
superagent是nodejs里一个非常方便的客户端请求代码模块,superagent是一个轻量级的,渐进式的ajax API,可读性好,学习曲线低,内部依赖nodejs原生的请求API,适用于nodejs环境下。

基本使用方法:
具体的请自行点击连接查看哟...

request
    .get("/login")
    .end(function(err, res){
        // code
    });
cheerio 页面数据解析
cheerio是一个node的库,可以理解为一个Node.js版本的jquery,用来从网页中以 css selector取数据,使用方式和jquery基本相同。

需要先loading一个需要加载html文档,后面就可以jQuery一样使用操作页面了。

基本使用方法:
具体的请自行点击连接查看哟...

const cheerio = require("cheerio");
const $ = cheerio.load("
    ...
"); $("#fruits").addClass("newClass");
使用Promise实现队列

这才是本篇文章的重头戏...

我们需要使用数组的一个方法 reduce()

arr.reduce([callback, initialValue])

有不太懂这个方法的可以查看我写的笔记:https://segmentfault.com/n/13...

reduce() 方法接收一个函数作为累加器(accumulator),数组中的每个值(从左到右)开始缩减,最终为一个值。

callback (执行数组中每个值的函数,包含四个参数)
initialValue (作为第一次调用 callback 的第一个参数。)

还有一个是Promise实现异步处理

有不太懂这个方法的可以查看我写的笔记:https://segmentfault.com/n/13...

具体是使用Promise的这个方法:
Promise.resolve()
这个方法返回一个fulfilled的Promise实例,或者原始的Promise实例。

代码实现:

// 实现队列 
// 本质: 对.then()方法实现累加 
let curPromise = urls.reduce((promise,curl) => {

    return promise.then(() => {
        return new Promise(resolve => {
            // 网络获取当前地址的网页内容
            requestGet(curl,() => {
                resolve(); 
            });
        });
    });

},Promise.resolve());
将数据写入result.json文件中

代码实现:

// 写入数据
curPromise.then(()=>{
    fs.writeFile("result.json", JSON.stringify(result), function (err) {
        if(err) throw new Error("appendFile failed...");
        console.log("数据写入success...");
    });    
});
完整代码
// 项目依赖
const cheerio = require("cheerio");
const agent = require("superagent");
const path = require("path");
const fs = require("fs");

// 地址数据
const urls = [{ 
    page:1,
    url:"https://www.imooc.com/course/list?c=fe&page=1"
},{
    page:2,
    url:"https://www.imooc.com/course/list?c=fe&page=2"
},{
    page:3,
    url:"https://www.imooc.com/course/list?c=fe&page=3"
}];

// 最终的数据
let result = [];


// 数据结构
/**
 * [
 *     {
 *         page: 1,
 *         data: [
 *                {title:xx,imgurl:xx...},
 *                ......
 *               ]
 *     }
 *     ......    
 * ]
 */


// 发起get请求
function requestGet(urlObj,callback){

    agent.get(urlObj.url)
     .end((err,res) => {
         if(err) throw new Error(err);

         // 分析页面
         let pageJson = analysis(res.text);

         // 拼接数据
         result.push({
             page:urlObj.page,
             data:pageJson
         });

         console.log(`写入第${urlObj.page}页的数据...`);

         // 执行回调
         callback();
     
     });
}


// 对网页分析
function analysis(data){

    let page = [];
    let $ = cheerio.load(data);
    let courseArr = $(".course-list").find(".course-card-container");
    courseArr.each((index,element) => {
        let _this = $(element);
        // 组装数据
        page.push({
            title:_this.find(".course-card-name").text(),
            imgurl:path.join("http:",_this.find(".course-card-top img").attr("src")),
            level:_this.find(".course-card-info span:first-child").text(),
            // level:_this.find(".icon-set_sns").parent().prev().text(),
            studynum:_this.find(".icon-set_sns").parent().text(),
            description:_this.find(".course-card-desc").text()
        });
    });
    return page;
}


// 实现队列 
// 本质: 对.then()方法实现累加 
let curPromise = urls.reduce((promise,curl) => {

    return promise.then(() => {
        return new Promise(resolve => {
            // 具体的内容
            requestGet(curl,() => {
                resolve(); 
            });
        });
    });

},Promise.resolve());

// 写入数据
curPromise.then(()=>{
    fs.writeFile("result.json", JSON.stringify(result), function (err) {
        if(err) throw new Error("appendFile failed...");
        console.log("数据写入success...");
    });    
});
启动项目
node app.js

可以看到终端有次序的输出了以下内容:

当打开生成的 result.json 文件,其结构也符合我们的预期:

至此,这篇文章也就结束啦,如果您有好的想法请留言哟。

持续学习中...

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/93607.html

相关文章

  • 资源集 - 收藏集 - 掘金

    摘要:行爬取顶点全网任意小说掘金之前连续多篇文章介绍客户端爬取平台,今天我们从零开始,实现爬取顶点小说网任意一本小说的功能。文件标记所有文件我的后端书架后端掘金我的后端书架月前本书架主要针对后端开发与架构。 30行js爬取顶点全网任意小说 - 掘金之前连续多篇文章介绍客户端爬取平台(dspider),今天我们从零开始,实现爬取顶点小说网任意一本小说的功能。 如果你还不知道客户端爬取,可以先看...

    stdying 评论0 收藏0
  • 资源集 - 收藏集 - 掘金

    摘要:行爬取顶点全网任意小说掘金之前连续多篇文章介绍客户端爬取平台,今天我们从零开始,实现爬取顶点小说网任意一本小说的功能。文件标记所有文件我的后端书架后端掘金我的后端书架月前本书架主要针对后端开发与架构。 30行js爬取顶点全网任意小说 - 掘金之前连续多篇文章介绍客户端爬取平台(dspider),今天我们从零开始,实现爬取顶点小说网任意一本小说的功能。 如果你还不知道客户端爬取,可以先看...

    马忠志 评论0 收藏0
  • 认识CSS样式

    摘要:声明在英文大括号中的的就是声明,属性和值之间用英文冒号分隔。嵌入式样式慕课网,超酷的互联网技术免费学习平台,创新的网络一站式学习实践体验服务及时贴心,内容专业有趣易学。6-2 css样式的优点   为什么使用css样式来设置网页的外观样式呢?右边编辑器是一段文字,我们想把“超酷的互联网”、“服务及时贴心”、“有趣易学”这...

    番茄西红柿 评论0 收藏0
  • 零碎笔记:浏览器访问一个网站所经历的步骤

    摘要:浏览器拿到了简书网的完整的页面代码,在解析和渲染这个页面的时候,里面的图片静态资源,他们同样也是一个个请求都需要经过上面的主要的七个步骤。浏览器根据拿到的资源对页面进行渲染,最终把一个完整的页面呈现给了用户。 浏览器访问一个网站所经历的步骤 Chrome搜索自身的DNS缓存 搜索操作系统自身的DNS缓存(浏览器没有找到缓存或缓存已经失效)查看Chrome浏览器的DNS缓存信息(chr...

    张金宝 评论0 收藏0
  • 课网_《Java消息中间件》学习总结

    摘要:时间年月日星期六说明本文部分内容均来自慕课网。这个时候,可以启动多台积分系统,来同时消费这个消息中间件里面的登录消息,达到横向扩展的作用。 时间:2017年07月22日星期六说明:本文部分内容均来自慕课网。@慕课网:http://www.imooc.com教学源码:无学习源码:https://github.com/zccodere/s... 第一章:课程介绍 1-1 课程安排 Java...

    twohappy 评论0 收藏0

发表评论

0条评论

XFLY

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<