[Nodejs入门]第四篇,用nodejs实现一个爬虫的功能

    功能很简单,制定一个网址,使用nodejs读取这个网址的源代码并打印出来

    大家知道,一个http请求涉及两个部分,一个是发起请求的客户端,一个是响应请求的服务端;nodejs内置的http和https模块主要就为我们提供了:http.ClientRequest对象和http.ServerResponse对象,看名字就能猜到,前面一个就是用来实现客户端的,而后面的就可以用来实现服务端

    在这个爬虫的例子里,我们只要用到ClientRequest即可,他的作用就是发起一个对远程地址的请求,并获取服务端返回的数据(对普通网页而言,就是页面的源代码)

    在使用之前,首先要引入http模块

    var http = require('http')

    创建一个http.ClientRequest对象,方法如下:

    http.request(options, function(response){})

    其中options是参数项,主要定义了一些请求的参数:必须的有这么几个

        hostname: 请求的主机名,这里一定要注意,前面不要'http://',后面不要有'/'

        path: 请求的路径,就是请求地址除了域名后面所有的内容,注意:一般开头都是'/'

        port: 端口,默认是80

  一般有这几个就够,举个例子,要请求的路径为: http://localhost/qq_29380855/article/details/50022737,option应该这样写

// 要获取的内容
var url = 'blog.csdn.net'
var path = '/qq_29380855/article/details/50022737'

var options = {
	hostname: url,			// 这里要注意下,不能带http,结尾不能带'/',不然,嘿嘿……报错
	port: 80,
	path: path				// 这里是域名后面的完整路径,一般用'/'开头
}
好了,完整代码:

var http = require('http')


// 要获取的内容
var url = 'blog.csdn.net'
var path = '/qq_29380855/article/details/50022737'

// 第一种:常规原生方法
var options = {
	hostname: url,			// 这里要注意下,不能带http,结尾不能带'/',不然,嘿嘿……报错
	port: 80,
	path: path				// 这里是域名后面的完整路径,一般用'/'开头
}

var req = http.request(options, function(response){	
	response.on('data', function(chunk){
		console.log(chunk)
		//console.log('request运行了,正在data中,已接收数据 ' + chunk.length)
	}).end()
猜猜显示的是什么?

 <Buffer 22 3e 3c 2f 61 3e 0d 0a 20 20 20 20 20 20 20 20 3c 2f 66 6f 72 6d 3e 0d 0a 20 20 20 20 3c 2f 75 6c 3e 0d 0a 3c 2f 64 69 76 3e 0d 0a 0d 0a 3c 73 63 72 ... >

这是些什么鬼?????好吧,看这句

console.log(chunk)
直接打印了数据块出来,这些数据块被放在缓冲区里,我们直接打印缓冲区的内容,就是这副样子,但是我们想要的是html代码,而不是这些看不懂的玩意,怎么办?很简单,修改上面那句为

console.log(chunk.toString())
重新执行,一大票html从屏幕刷过,靠,有没有点黑客的赶脚捏??

再一个要注意的点,使用http.request必须使用end()方法结束,不然会报错,好吧,其实你真要忘了也没太大问题,编译不会通过的,我反正每次都不记得

上面的代码使用 var req = http.request(...) 把返回的ClientRequest赋值给了req变量,一般情况下不需要这样做,这里这样写是为了后面测试ClientRequest事件用的。所以一般只要 http.request(options, function(response){})... 就可以了

大家知道在nodejs里一般回调的第一个参数都是err,但是在request的回调中只有一个response,官方叫IcommingMessage,顾名思义就是接收到的信息,所以在这里如果要捕捉错误,需要用try... catch

当然啦,上面只是简单输出了页面的源代码,一般情况下我们需要把获取到的内容保存下来,怎么做呢?很简单

var html = ''
http.request(options, function(response){
	var str = ''
	response.on('data', function(chunk){
		str += chunk	
	})
	response.on('end', function(){
		html = str
	})
}).end()
console.log(html)
似乎没啥问题,但最终打印出来的结果是空,为啥捏?

nodejs很容易出这样的问题,因为他的任务是异步的,在console.log(html)这句的时候,从服务器拉取信息的任务还没完成,html = str这句根本没有执行,这是打印出来的自然就是空了,所以在这里需要定义一个函数,告诉系统当内容都拉取到之后干什么,如:

function showHtml(html){
    // 当然实际应用中不会这么简单,应该会做一些关键字抽取、文件保存之类的操作,这里仅说明问题
    console.log(html)
}

http.request(options, function(response){
    var html = ''
    response.on('data', function(chunk){
        html += chunk
    })
    response.on('end', function(){
        showHtml(html)
    })
})

好了,就这么简单,另外告诉大家一个很恶心的事情,在一个项目中,用http.request方法获取大量json字符串,出现了字符串被截断的情况惊恐想了很多办法没能解决,不得已(其实也没那么纠结,毕竟这块代码很简单,替换很快)使用request模块来获取内容,搞定,所以,你如果只是想实现这样的功能,那么上面的内容有可能白看了,因为直接调用下面的代码就得了大笑

var request = require('request')
// 第二种:牛逼的request
request('http://www.baidu.com', function(err, response, body){
	if(err) return console.log(err)
	console.log(body)
})
关于回调函数的参数简单说明下:  response包含请求的详细信息,也包括body的所有内容。body是 页面的主体部分,就是我们想要的html代码,大家自己试试就清楚了


展开阅读全文

没有更多推荐了,返回首页