nodejs入门(一)URL与HTTP

相关

说点啥

一直想做一个属于自己的应用。于是“被迫”就来学一门后台相关的语言。以前从没搞过相关的,node应该算是我的启蒙语言了吧。

js嘛 很难想不到JavaScript,学会了这个,是不是再学Web就简单了?

我是从慕课网看视频学起的,这篇文章算是学习笔记吧,视频地址见下面的相关

API

URL

对应api地址:https://nodejs.org/api/url.html

对应慕课网视频地址:http://www.imooc.com/video/6710

api里乍一看啥玩意儿啊,全是英文,然后我就去看视频了。看完视频反过来再看api,卧槽,原来前面那一大坨Example是这个啊,哈哈,我们一起来看

我们在cmd中输入node,回车,便进入了nodejs的环境。 输入url,回车,我们会看到:

{
  parse: [Function: urlParse],
  resolve: [Function: urlResolve],
  resolveObject: [Function: urlResolveObject],
  format: [Function: urlFormat],
  Url: [Function: Url] 
}

这就是我们url的几个方法。其中最重要的当属 parse 了。 api中如下,我也不懂。。。:

url.parse(urlStr, [parseQueryString], [slashesDenoteHost])

parse基础

作用:解析 url

输入:url.parse(‘http://www.flowerfat.com‘)
输出:

{
  protocol: 'http:',
  slashes: true,
  auth: null,
  host: 'www.flowerfat.com',
  port: null,
  hostname: 'www.flowerfat.com',
  hash: null,
  search: null,
  query: null,
  pathname: '/',
  path: '/',
  href: 'http://www.flowerfat.com/' 
}

跟着视频走到这里的时候,虽然scott哥说了每个的含义,不过还是没咋懂啊!直到后来看到api我说的那一坨,哦吼,每个都有对应的解释啊。
具体我就不多说了,英文也不难,大家一看就懂了

parse进阶

输入:url.parse(‘http://www.flowerfat.com‘, true)
第二个参数的目的:解析query时,是否用QueryString这个module。
这个设置为true的时候,解析到的query就成了键值对的形式。

输入:url.parse(‘//www.flowerfat.com’, true)
出问题了,host都得不到

输入:url.parse(‘//www.flowerfat.com’, true, true)
结果正确了,第三个参数默认是false,这里设置成true ,就能正确解析了。
这里我没懂,scott哥也没说这个参数是干啥的。不过我们来看api中:slashesDenoteHost是第三个参数的名字,百度了下,网上的说法是它会去认//与/,这两个中间的当作host。

具体我也不造理解的对不,又懂得朋友可以批评指教。

format

作用:与parse相反,即把上面解析输出的结果丢到这个函数里,返回url输入

输入:url.format( {protocol: ‘http:’,……,path: ‘/’,href: ‘http://www.flowerfat.com/’ } );
输出:’http://www.flowerfat.com

resolve

作用:我理解是拼接,有一定规则的拼接

详情正如api里的Example:

url.resolve('/one/two/three', 'four')         // '/one/two/four'
url.resolve('http://example.com/', '/one')    // 'http://example.com/one'
url.resolve('http://example.com/one', '/two') // 'http://example.com/two'

Query Strings

懂的人都知道,我们用get方法跟服务器交流的时候,’?’后面的请求参数很重要。那么这个问号后面的请求参数就是我们parse后的query的值

对应api地址:https://nodejs.org/api/querystring.html

对应慕课网视频地址:http://www.imooc.com/video/6711

stringify

序列化:把键值对变成网址的形式

parse ###

反序列化:相当于前面我们提到的url.parse方法中的第二个参数,这是为true

escape、unescape

转义和反转义

HTTP源码

这可是个大工程,视频里在这部分说了一堆,我表示我睡着了。。。

中间部分都是一些需要了解的概念和知识,这些有助于我们后面关于HTTP源码的了解,这里就不赘述了。

对应api地址:https://nodejs.org/api/http.html

对应慕课网视频地址:http://www.imooc.com/video/7963

直接来看源码部分(源码来自Github!but!我在github上找不到视频里的那个工程啊,什么鬼,于是就选了个下面的这个,朋友们海涵)

nodejs对应源码地址:https://github.com/nodejs/node

然后在github页面按下t, 就是工程的搜索功能!卧槽,这个有点厉害 然后搜索http.js,就是我们要的HTTP的源码了哈

var http = require('http')

http
    .createServer(function(req, res) {
        res.writeHead(200, {'Content-Type':'text/plain'})
        res.write('Hello Ming')
        res.end()
    })
    .listen(2015)

我表示这段真没啥好说的。视频里针对上面代码的由来,追踪了下github上的源码。十几分钟的视频下来我是懵圈了,根本不明所以。朋友们你们加油,不说了,都是泪。

HTTP 爬虫

作为一个干活分享者,显然上面的乱七八糟的不是我的风格,这里继续copy视频里的好东西。

对应视频地址:http://www.imooc.com/video/7965

目的

所谓爬数据,我理解就是把我们需要的东西get到。(其实爬网页对html也要有一定了解)

执行1

为了方便爬,我们按照作者的意思,安装一个插件 :npm install cheerio ,目的是快速找到我们要爬的数据

在网页上审查元素,找到我们想要的:

// <div class="mod-chapters">
//   <div class="chapter chapter-active">...</div> 后面的active表示这个item是否展开
//   <div class="chapter chapter-active">...</div>
//   <div class="chapter">...</div>
//   <div class="chapter">...</div>
//   <div class="chapter">...</div>
// </div>

主要代码(不要问我res.on(‘data’, function(data)里的data是哪儿来的,下篇文章见):

var http = require('http')
var cheerio = require('cheerio')
var url = 'http://www.imooc.com/learn/348'

// 相当于main 我们在这里解析html
function filterChapters(html){
    var $ = cheerio.load(html)
    // 这个跟视频里的learnchapter不同,可能是慕课网改了吧
    // 通过这个方法就拿到了类名
    var chapters = $('.chapter')
    // 打印数组的长度
    console.log('打印 '+chapters.length)
}

http.get(url, function (res) {
    var html = ''

    res.on('data', function(data) {
        html += data
    })

    res.on('end', function(){
        filterChapters(html)
    })
}).on('error', function() {
    console.log('获取网站数据出错!')
})

我们引入了cheerio,并用它来更好的get对应的数据

这里我们看,跟之前的代码比较,就多了个函数:filterChapters
在接收完毕网页后,把网页数据传到这个函数里,进行整理。

在cdm中执行上面的代码:

node crawierPlus.js

打印结果如下:

打印 5

执行2

显然一个数组长度不是我们想要的,继续,嘿咻嘿咻!
由执行1看到,chapters这个“数组”就是我们要的内容了。我们继续解析,如何拿到标题呢?

看网页的相关审查元素:

chapters.each(function(item){
    var chapter = $(this)
    var chapterTitle = chapter.find('strong').text()
    console.log(chapterTitle + '\n')
})

通过each方法,得到每个chapter。通过find的方法,得到strong,在.text()得到strong里的text
再来看对应video的获取:

从图上能看出,video下有两个对应的条目

chapters.each(function(item){
    var chapter = $(this)
    var chapterTitle = chapter.find('strong').text()
    console.log(chapterTitle + '\n')
    var videos = chapter.find('.video').children('li')

    videos.each(function(item){
        var video = $(this).find('.studyvideo')
        var videoTitle = video.text()
        var id = video.attr('href').split('video/')[1]
        console.log('【'+id+'】  '+videoTitle)
    })
})

对比上面的find方法,我们发现’strong’和’.video’有个不同点,’.video’前面有个’.’,大胆假设,因为video是一个class,而strong不是。故而有此区别
跑一遍上面的code,我们就能看到一个很好看的结果了。

我们是打log,而视频里作者是把数据都封装到了一起,用的是push的方法,具体我也不懂,就不瞎bb了。

Code

var http = require('http')
var cheerio = require('cheerio')
var url = 'http://www.imooc.com/learn/348'

function filterChapters(html){
    var $ = cheerio.load(html)
    var chapters = $('.chapter')

    var courseData = []

    chapters.each(function(item){
        var chapter = $(this)
        var chapterTitle = chapter.find('strong').text()
        var videos = chapter.find('.video').children('li')

        var chapterData = {
            chapterTitle: chapterTitle,
            videos:[]
        }

        videos.each(function(item){
            var video = $(this).find('.studyvideo')
            var videoTitle = video.text()
            var id = video.attr('href').split('video/')[1]

            chapterData.videos.push({
                title:videoTitle,
                id: id
            })
        })

        courseData.push(chapterData)
    })

    return courseData
}

function printCourseInfo(courseData){
    courseData.forEach(function(item){
        var chapterTitle = item.chapterTitle
        console.log(chapterTitle + '\n')
        item.videos.forEach(function(video){
        console.log(' 【'+video.id+'】 '+ video.title + '\n')
        })
    })
}

http.get(url, function (res) {
    var html = ''

    res.on('data', function(data) {
        html += data
    })

    res.on('end', function(){
        var courseData = filterChapters(html)
        printCourseInfo(courseData)
    })
}).on('error', function() {
    console.log('获取网站数据出错!')
})

个人博客

欢迎来访我的干货个人博客:http://www.flowerfat.com

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值