nodejs入门(一)URL与HTTP
2015-10-16 16:08
721 查看
相关
官网:https://nodejs.org/en/API:https://nodejs.org/api/
慕课网:进击Node.js基础(一):http://www.imooc.com/learn/348
说点啥
一直想做一个属于自己的应用。于是“被迫”就来学一门后台相关的语言。以前从没搞过相关的,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方法中的第二个参数,这是为trueescape、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
![](http://i.imgur.com/18RzCe9.png)
目的
所谓爬数据,我理解就是把我们需要的东西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这个“数组”就是我们要的内容了。我们继续解析,如何拿到标题呢?
看网页的相关审查元素:
![](http://i.imgur.com/f67MSrf.png)
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的获取:
![](http://i.imgur.com/VTLj6E7.png)
从图上能看出,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相关文章推荐
- Python BaseHTTPServer 模块解析
- Junipor交换机 HAS BOOTED FROM THE BACKUP JUNOS IMAGE
- Raspberry Pi 图片网络化--curl 上传文件至Aliyun的ftp服务器
- Junipor交换机 ssh_exchange_identification: Connection closed by remote host
- Linux网络编程入门
- Android自定义框架之网络请求 .
- 从0开始学Java——JSP&Servlet——HttpServletRequest相关的几个路径信息
- http://images.google.com/searchbyimage?site=search&image_url= 搜索
- 《深入理解Linux网络技术内幕》阅读笔记(三十三)
- Android网络通信android-async-http入门
- 运营商网络中的"在线"加密(二)
- Spring HTTP Invoker
- TCP协议RST:RST介绍、什么时候发送RST包
- HTTP请求中浏览器的缓存机制
- 电信CDMA 无线网络优化 基础知识
- HTTP请求中浏览器缓存
- 网络通信 --> select()用法
- Could not load type System.ServiceModel.Activation.HttpModule解决办法
- Android Studio中添加对HttpClient的支持包
- 安卓访问网络常用的3种方式(httpClient, httpUrlConnection,android-query ajax)及cookie处理