了不起的Node.js【1】——了解Node.js+爬虫demo

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/w8897282/article/details/79745843

本篇博文内容参考慕课网的课程如下:
进击Node.js基础(一)
创业公司的Nodejs工程师

有时间的小伙伴可以去参考学习一下此视频。

前言

所谓3W就是what、why、when,即解析如下三个问题:
【1】什么是Node.js?
【2】为什么用Node.js?
【3】什么时候选择用Node.js?

上述三个问题,参考:创业公司的 Node.js 工程师

什么是Node.js

Node.js是由C++编写的,本质上是一个javaScript的运行环境,他不仅可以解析js代码(无浏览器安全级的限制),还提供许多系统级别API,例如文件读写、网络通信等。

做一些类比,apache相当于一个容器,可以放一些前端的工程在里面,同时为了能够进行数据库操作或者网络通信,我们会用一些后台脚本语言,比如PHP或者JAVA(对应的容器就是Tomcat)。这种技术架构下,就是apache+php或则tomcat+java。

而Node.js个人的理解,就像是把apache和PHP集成到一起的一个运行环境,即Node本身提供js的运行环境(相当于apache的功能),我们编写的js文件(类似PHP文件),负责完成业务逻辑、进行数据库操作、网络请求等工作。

这是一种通过 js语言开发web服务端的东西,具有非阻塞,事件驱动IO等特性,从而让高并发在轮询和comet构建的应用中成为可能。

浏览器给网站发送请求的过程一直就没怎么变过。当浏览器给网站发送请求后。服务器收到请求,然后搜索被请求的资源,必要的时候还会查询以下数据库,最后把相应的结果返回给浏览器。不过在传统的服务器中(例如apache中),每一次请求都会在服务端创建一个线程。

扫描二维码关注公众号,回复: 2896418 查看本文章

后来有了ajax后,我们不必每次都请求一个完整的页面,每次只请求需要的部分的信息就可以了。由于http的无状态性,一次请求就是一次响应。当我们需要保持实时更新(数据同步)时,我们就需要让用户和服务器保持一个长时间的轮询(每隔5s请求一次服务器之类)

再回来看传统的服务器,每次一个新用户连接到你的网站上,服务器就需要创建一个连接。每个连接都需要占用一个线程,但这些线程可能大部分时间都是空闲的(没有处理用户的请求),但这并不意味着他们不占用内存。所以当连接数达到一定数量后,服务器的资源就会被消耗殆尽。简单讲,就是占用了资源,却没最大化地利用资源。

解决的办法就是【非阻塞】和【事件驱动】。非阻塞的服务器就像是一个loop循环。这个loop会一直跑(永远不会空闲地从头遍历到尾),一但新请求进来后,loop就接受了这个请求,然后把它传递给了其他进程(比如给了一个搞数据查询的进程),然后响应一个回调(callBack),然后loop就接着遍历接受其他的请求。可以理解为loop线程只负责接受和转发请求,具体的工作(数据库查询、业务逻辑等)统统交由其他线程处理,这样服务器就不会像之前那样傻等着数据库返回结果了。

这是如果数据库把结果返回了,loop就把结果传回用户的浏览器。这种模式线下,服务器的进程就不会空闲。从而在理论上说同一时刻的数据库查询数量以及用户请求的数量就没有限制了。服务器只在用户那边有事件发生的时候才响应,这就是事件驱动。

Node.js的应用是通过javascript开发的,然后直接在Google的变态V8引擎上跑。用了Node.js,你就不用担心用户端的请求会在服务器里跑了一段能够造成阻塞的代码了。因为javascript本身就是事件驱动的脚本语言。你回想一下,在给前端写javascript的时候,更多时候你都是在搞事件处理和回调函数。javascript本身就是给事件处理量身定制的语言。

为什么学习Node.js

【1】Node很火
【2】Node.js很强:
image.png

推荐经常去的几个网站:
Node中文网
npm 中文文档
Node中文社区
Node-gitHub
stackoverflow技术问答社区

什么时候选择Node.js

1. 期望的迭代节奏

任何一个产品,立项之初,都有它特殊的商业背景和商业目标,在这个背景和目标下,会给予对它的一些期望,希望它以怎样形式,多长时间开发上线,上线后,以多长的周期进行版本的更新迭代,这些都很好理解,如果是一个展示型的,扔上去不需要怎样去增加功能,也不需要多么频繁的改版升级,那么就没必要一定要使用 Nodejs,用 PHP,Ruby 统统没问题。

2. 团队工程师能力

我们知道,就像这世界的大部分事物一样,工程师的能力也是大概符合正态分布,除去特别弱的,比如 3 年前的我,除去特别强的,大部分工程师其实都处在中间的这个地带,就像现在的我,对于 Nodejs 及周边生态的掌握可能比较好,但不是特别特别好,而 Nodejs 又是一个新的职业方向,火热的市场上根本没有足够时间来沉淀,于是大部分的创业团队是并没有足够资深的 Nodejs 工程师,这意味着我们在快速开发的时候,往往也面临着更高的业务风险,一旦 Nodejs 用的姿势不对或者技术选型失误,会给业务带来灾难性的打击。

这一点其实被很多公司所忽视,整个团队在当下与未来半年的一个规模,团队成员的技术背景,自我学习的能力,对于新技术升级的接受程度,如果是不能很好的驾驭 Nodejs 而且自学能力又偏弱的话,就需要慎重考虑一下。

3. 跟产品的匹配程度

其实创业类的产品,往往很少有上来就规模化,高难度的,所以许多类型都适合,我们与其想那些可以用 Nodejs 开发,不如反过来看,那些类型的不太适合用 Nodejs 开发,排除掉这些场景,剩下的都可以评估一下用 Nodejs 是不是可以。

我这里罗列了几种,其实大家照着这个方向走,未必只有这 4 点:

  • 极高并发数
  • 密集 CPU 运算
  • 高安全高可靠性
  • 内存精密控制及释放

第一个服务器

我们首先在桌面上创建一个node的文件夹,然后创建一个js文件,命名为web-service,在里面输入如下代码,这里查看官网的实例代码:

//加载http的模块,创建http,处理相关任务
var http=require('http');
//创建web服务器,传入请求和响应
var serv=http.createServer(function (req,res){
    res.writeHead(200,{'content-Type':'text/html'});
    res.end('<p>hello world!</p>');
});
//在3000端口监听请求
serv.listen(3000);

然后cd到node文件下,输入

node web-service.js

image

然后在浏览器输入地址:
image

模块与包管理工具

我们可以用过var或者function可以定义一个全局访问的变量或者函数,但是当多人协作的时候或者大量的js文件的时候,批量引入到某个页面时,就可能出现变量覆盖或者重写的情况,特别是当js模块之间存在着依赖关系的时候,非常容易导致页面出错。

这主要是因为js天生就缺少一套模块管理机制来隔离实现不同功能的js片段避免他们相互污染。为此,我们通常采用命名控件的方法,把函数和变量限制在某个特定的作用域内,强制约定一套命名规范来约束代码,从而保证代码的安全执行。
image

common.js是一套规范,它约定了JavaScript该如何去组织,如何去编写。首先是把执行不同任务的特定的代码快或者代码文件看做是一个独立的模块,每一个模块可以看做是一个独立的作用域,但并不是孤立的,可能存在着依赖关系。每一个模块都可以具体到三个关键部分,分别是模块的定义、标识和引用。common.js的设计规范在社区内不断的成长壮大,对许多开源的产品产生了积极的作用。
这里写图片描述
node.js借鉴了common.js的模块组织理念,并基于common.js的规范实现了一套模块管理系统。在node.js中,每一个js文件都可以看做是一个独立的模块,在模块里面不需要有命名空间,也不需要担心有变量污染和方法定义时的覆盖。我们在安装node.js的时候同时会安装nmp这个包管理工具,通过这个工具,我们可以往项目中添加形形色色的js模块。npm的作用类似于maven和gradle。

在node.js中文件和模块是一一对应的。模块有几种不同类型,可以划分为核心模块、文件模块和通过nmp安装的第三方模块。

【实例】一个Node爬虫

实现爬虫思路:
(1)、node模拟Http请求,请求待爬取页面的html
(2)、对网页包含关键信息的html结构进行分析
(3)、使用框架对html进行关键数据提取
(4)、对数据进行处理及分析

1、首先我们创建一个文件夹 Crawler,用webStorm打开,然后创建http.js,我们使用 require 指令来载入 http 模块,并将实例化的 HTTP 赋值给变量 http。

由于这里需要发送网络请求和进行html解析,所以我们使用request模块来发送Http请求,为此新建一个package.json的文件

{
  "name": "Crawler",
  "version": "0.0.1",
  "dependencies": {
    "request": "^2.83.0"
  }
}

或者新建完成后输入request的安装命令

npm init //初始化
npm install express request cheerio --save

其中:request——负责网络请求;cheerio——负责解析装载的Html

完整案例代码如下:

var http = require("http");
var request = require('request');
var cheerio = require('cheerio');
var $;

//设置请求头(cookie)和地址
var options = {
    url: "http://www.imooc.com/learn/947",
};

//html
var html =''
var chapter
var infos=[]

function callback(error, response, body) {
    if (!error && response.statusCode === 200) {
        html =body;
        $= cheerio.load(html);
        var chapters=$(".chapter")

        var title
        var lessons
        var infoData
        //遍历每一个章节
        chapters.each(function(i){
            chapter=$(this)
            title=formatStr(chapter.find('strong').text())

            infoData={
                title:title,
                lessons:[]
            }

            //遍历课程
            lessons=chapter.find('.video').children('li')
            var lesson
            lessons.each(function(i){
                lesson=$(this).find('.J-media-item')
                infoData.lessons.push({
                    name:formatStr(lesson.text()),
                    id:lesson.attr('href').split('/')[2]
                })
            })

            infos.push(infoData)
        })
        printInfos(infos)
    }
}


request(options, callback);

function printInfos(infos){
    var title
    var lessons
    infos.forEach(function(info){
        title=info.title
        lessons=info.lessons
        console.log(title+"\n")
        lessons.forEach(function (lesson) {
            console.log(lesson.id+"|"+lesson.name)
        })

    })
}
function formatStr(str){
    return str.replace(/[\r\n]/g,"").trim()
}

这里比较难的地方就是在于对cheerio 的使用,其语法和Jquery的选择器很像,具体的API可以参考其官方文档。

欢迎关注微信公众号~
这里写图片描述

总结

这里只对node进行了简单的介绍,后续会对node的api和demo继续记录,谢谢大家关注~

猜你喜欢

转载自blog.csdn.net/w8897282/article/details/79745843