刚学Nodejs不久,写了个抓页面的,但是返回不了结果。求大神指正
刚学Nodejs不久,写了个抓页面的,但是返回不了结果。求大神指正
这个是Server,客户端会用Ajax请求这个地方 // Nodejs部分,主要作用是接收前端关键词,抓取百度知道页面。返回页面给前端 var http = require(‘http’); var cheerio = require(‘cheerio’); var iconv = require(‘iconv-lite’); http.createServer(function (req, res) { res.writeHead(200, { ‘Content-Type’: ‘text/html’, ‘Access-Control-Allow-Origin’ : ‘*’ }); var postData = “”; var ret = 0; req.setEncoding(‘utf-8’); req.addListener(‘data’, function(chunk){ postData += chunk; }); req.addListener(‘end’, function(){ var value = postData.replace(/kw=/, ‘’), result = 0; doRequest(value, 0); }); res.end(’{“rank”:’+result+’}’); }).listen(10088);
这个是当server端得到数据后,会请求这个doRequest方法,这里面会去抓百度的页面,计算出关键词排的在第几返回出来。 var doRequest = function(kw, page){ page = page * 10; var options = { host: ‘zhidao.baidu.com’, port: 80, path: ‘/search?word=’+kw+’&pn=’+page }; http.get(options, function(res) { var buffers = [], size = 0; res.on(‘data’, function(buffer) { buffers.push(buffer); size += buffer.length; }); res.on(‘end’, function() { var buffer = new Buffer(size), pos = 0; for(var i = 0, l = buffers.length; i < l; i++) { buffers[i].copy(buffer, pos); pos += buffers[i].length; } var gbk_buffer = iconv.decode(buffer,‘GBK’); $ = cheerio.load(gbk_buffer.toString()); // 获取页面前三个的优质回答 var target = “DARRY RING”; var isBreak = false; var htmlTop = $("#cluster-items").find(".con-all").slice(0, 3); htmlTop.each(function(){ var tContent = $(this).text().replace(/\s+/g, “”); tContent = tContent.toLowerCase(); if (tContent.indexOf(“darryring”) > 0 ){ // 当找到DY的时候,退出循环 isBreak = true; return false; } }); if (isBreak == true){ return {keyword : kw, score : 1}; } var html = $("#wgt-list").find(“dd.answer”); var n = 0; html.each(function(i, elem){ var content = $(this).text().replace(/\s+/g, “”); content = content.toLowerCase(); if (content.indexOf(“darryring”) > 0 && n <= html.length ){ n = i + 1; return false; } }); if(n == 0){ page++; if (page < 5){ doRequest(kw, page); }else{ return {keyword : kw, score : 9999}; } }else{ var num = page + n; return {keyword : kw, score : num}; } }); res.on(‘error’, function(e){ console.log("Got error: " + e.message); }) }) }
现在就是调试的时候,doRequest里面都成功了,但是不返回到客户端。求指正啊,我要怎么改?以前没写过异步
根据你描述的情况,问题可能出在异步操作上。在Node.js中,处理异步操作需要特别注意回调函数和异步流程控制。你的doRequest
方法中的逻辑是异步执行的,而你试图立即返回结果。你需要确保在所有异步操作完成后才返回结果。
以下是一个改进后的示例代码,使用回调函数来处理异步操作,并确保返回结果:
var http = require('http');
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'});
var postData = "";
req.setEncoding('utf-8');
req.on('data', function(chunk) {
postData += chunk;
});
req.on('end', function() {
var value = postData.replace(/kw=/, '');
doRequest(value, 0, function(result) {
res.end(JSON.stringify({rank: result}));
});
});
}).listen(10088);
var doRequest = function(kw, page, callback) {
page = page * 10;
var options = {
host: 'zhidao.baidu.com',
port: 80,
path: '/search?word=' + encodeURIComponent(kw) + '&pn=' + page
};
http.get(options, function(res) {
var buffers = [], size = 0;
res.on('data', function(buffer) {
buffers.push(buffer);
size += buffer.length;
});
res.on('end', function() {
var buffer = Buffer.concat(buffers, size);
var gbk_buffer = iconv.decode(buffer, 'GBK');
var $ = cheerio.load(gbk_buffer.toString());
var target = "DARRY RING";
var isBreak = false;
var htmlTop = $("#cluster-items").find(".con-all").slice(0, 3);
htmlTop.each(function() {
var tContent = $(this).text().replace(/\s+/g, "");
tContent = tContent.toLowerCase();
if (tContent.indexOf(target.toLowerCase()) > -1) {
isBreak = true;
return false;
}
});
if (isBreak) {
callback({keyword: kw, score: 1});
return;
}
var html = $("#wgt-list").find("dd.answer");
var n = 0;
html.each(function(i, elem) {
var content = $(this).text().replace(/\s+/g, "");
content = content.toLowerCase();
if (content.indexOf(target.toLowerCase()) > -1 && n <= html.length) {
n = i + 1;
return false;
}
});
if (n == 0) {
page++;
if (page < 5) {
doRequest(kw, page, callback);
} else {
callback({keyword: kw, score: 9999});
}
} else {
var num = page + n;
callback({keyword: kw, score: num});
}
});
}).on('error', function(e) {
console.log("Got error: " + e.message);
});
};
解释
-
HTTP Server:
- 在
req.on('end')
回调中调用doRequest
方法,并传递一个回调函数callback
。 - 在
doRequest
的回调函数中,使用res.end
发送最终结果。
- 在
-
doRequest:
- 使用
http.get
进行异步请求。 - 在
res.on('end')
回调中处理响应数据。 - 使用
Buffer.concat
合并缓冲区。 - 使用
iconv.decode
解码GBK编码的数据。 - 使用
cheerio
解析HTML。 - 在完成所有处理后,调用
callback
函数返回结果。
- 使用
通过这种方式,你可以确保在所有异步操作完成后才返回结果。
根据你的描述,问题出在 doRequest
方法的异步调用上。由于 http.get
是一个异步操作,所以在 doRequest
方法中没有直接返回结果。你需要使用回调函数来处理异步操作的结果,并将其传递回客户端。
以下是修改后的代码示例:
var http = require('http');
var cheerio = require('cheerio');
var iconv = require('iconv-lite');
http.createServer(function (req, res) {
res.writeHead(200, {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'});
var postData = "";
req.setEncoding('utf-8');
req.on('data', function(chunk) {
postData += chunk;
});
req.on('end', function() {
var value = postData.replace(/kw=/, '');
doRequest(value, 0, function(result) {
res.end(JSON.stringify({rank: result}));
});
});
}).listen(10088);
var doRequest = function(kw, page, callback) {
page = page * 10;
var options = {
host: 'zhidao.baidu.com',
port: 80,
path: '/search?word=' + encodeURIComponent(kw) + '&pn=' + page
};
http.get(options, function(res) {
var buffers = [], size = 0;
res.on('data', function(buffer) {
buffers.push(buffer);
size += buffer.length;
});
res.on('end', function() {
var buffer = Buffer.concat(buffers, size);
var gbk_buffer = iconv.decode(buffer, 'GBK');
var $ = cheerio.load(gbk_buffer.toString());
var isBreak = false;
var htmlTop = $("#cluster-items").find(".con-all").slice(0, 3);
htmlTop.each(function() {
var tContent = $(this).text().replace(/\s+/g, "");
tContent = tContent.toLowerCase();
if (tContent.indexOf("darryring") > -1) {
isBreak = true;
return false;
}
});
if (isBreak) {
callback({keyword: kw, score: 1});
return;
}
var html = $("#wgt-list").find("dd.answer");
var n = 0;
html.each(function(i, elem) {
var content = $(this).text().replace(/\s+/g, "");
content = content.toLowerCase();
if (content.indexOf("darryring") > -1 && n <= html.length) {
n = i + 1;
return false;
}
});
if (n == 0) {
var nextPage = page + 10;
if (nextPage < 50) {
doRequest(kw, nextPage, callback);
} else {
callback({keyword: kw, score: 9999});
}
} else {
var num = page + n;
callback({keyword: kw, score: num});
}
});
res.on('error', function(e) {
console.log("Got error: " + e.message);
callback({keyword: kw, score: 9999});
});
});
};
解释
- 回调函数:在
doRequest
中添加了一个回调函数callback
,用于处理异步操作的结果,并将其传递回客户端。 - 异步操作:在
http.get
的回调中处理异步操作的结果,并调用callback
函数将结果传递回去。 - 编码处理:使用
Buffer.concat
替换原有的手动拼接 Buffer 的方式,使代码更简洁。
通过这种方式,你可以确保异步操作的结果能够正确地返回到客户端。