项目初始化

创建一个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('<ul id="fruits">...</ul>');
$('#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 文件,其结构也符合我们的预期:

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

持续学习中...

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

  1. python爬虫图片实例-Python爬虫爬取煎蛋网图片代码实例

    这篇文章主要介绍了Python爬虫爬取煎蛋网图片代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 今天,试着爬取了煎蛋网的图片. 用到的包: ...

  2. python爬图代码实例_Python爬虫爬取煎蛋网图片代码实例

    这篇文章主要介绍了Python爬虫爬取煎蛋网图片代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 今天,试着爬取了煎蛋网的图片. 用到的包: ...

  3. Python爬虫爬取煎蛋网图片代码实例

    这篇文章主要介绍了Python爬虫爬取煎蛋网图片代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 今天,试着爬取了煎蛋网的图片. 用到的包: ...

  4. python爬虫爬取慕课网中的图片

    我们简单地爬取慕课网中免费课程下的第一页的图片,如想爬取多页图片,可以添加for循环自行实现 python版本:3.6.5 爬取网址:http://www.imooc.com/course/list ...

  5. 小白scrapy试炼-爬取慕课网免费课程

    本文参考博客: scrapy爬虫-爬取慕课网全部课程 scrapy爬虫框架入门实例 准备工作: anaconda(为了简单安装scrapy) 安装scrapy的方法有好多种,原来在pip上花了挺多时间 ...

  6. Python爬虫学习笔记 (9) [初级] 小练习 爬取慕课网课程清单

    更新日期: 2021.03.28 本节学习内容 : 练习使用 bs4 和 xlwings - 爬取慕课网免费课程清单并存为 Excel 文件. 目录 1. 目标信息 2. 爬取步骤 3. 代码 5. ...

  7. 100行代码教你爬取斗图网(Python多线程队列)

    100行代码教你爬取斗图网(Python多线程队列) 前言 根据之前写的两篇文章,想必大家对多线程和队列有了一个初步的了解,今天这篇文章就来实战一下,用多线程 + 队列 爬取斗图网的全网图片. 你还在 ...

  8. python爬取小说基本信息_python实战项目:爬取某小说网

    项目文档: 项目简介: 爬取某小说网首页中的全部小说,并储存到数据库中 项目版本 :python2.7.12 项目源码: 源码已上传 github: 源码github 项目总览: 1. 爬取小说首页中 ...

  9. 爬虫笔记——多线程爬取斗图网表情包(threading)

    爬虫笔记--多线程爬取斗图网表情包(threading) 网站观察 爬取框架 具体代码 斗图网网址:斗图网,这里以爬取最新套图为例. 网站观察 在网页翻页操作中可以看到网页是非动态加载的(page为页 ...

最新文章

  1. 终于有人把中台说清楚了
  2. 02-线性结构3 Reversing Linked List
  3. Cisco PT模拟实验(12) 路由器静态路由的配置
  4. 厉害了!Python+matplotlib制作8个排序算法的动画
  5. Android调试相关的技术常识
  6. hibernate数据的三种存在状态(只与事务有关)
  7. 有用的Chrome扩展介绍 - Octotree - GitHub code tree
  8. Spring 4 官方文档学习(十)数据访问之JDBC
  9. vim复制、删除和粘贴一行
  10. 恋舞服务器维修,2144《梦幻恋舞》关闭充值及关服公告
  11. Java8————Stream API
  12. pandas筛选某个列值是否位于某个列表内
  13. 苹果id无法登陆_《英雄联盟手游》苹果id和拳头账户合并教程 苹果id如何绑定拳头账号...
  14. 计算机软件设计费计算标准,水利工程咨询、勘测设计费收费标准及计算程序
  15. 小白学习MySQL - 一次慢SQL的定位
  16. 【bzoj1818】[Cqoi2010]内部白点
  17. layui 日期选择器 laydate详细参数用法大全,一键复制粘贴
  18. Hinton 深度学习论文总结
  19. 问题1084:搭数字Ⅰ
  20. 传感器实验——寻迹模块

热门文章

  1. [转载]生活在 Emacs 中
  2. 软工实践第八次作业(软件工程实践总结)
  3. Leetcode: 2. Add Two Numbers
  4. android scrollview listview显示不全
  5. cocos2d-x中使用可加密Sqlite存储玩家数据
  6. 《精通.Net核心技术》
  7. C++11---之auto
  8. LeetCode-20.有效的括号(栈的使用+map的count)
  9. java海滩上有一_海滩上有一堆桃子,五只猴子来分-海滩上有一堆桃子,五只猴子来分java实现-吾爱编程网...
  10. java jar包存放位置_获得运行jar包存放路径的方法