使用superagent爬取网站内容,当网页编码不是utf-8
编码时,中文就会返回乱码,原因是superagent只支持utf-8的网页编码,我们可以使用其扩展的一个npm模块superagent-charset
superagent-charset使用说明
superagent-charset扩展了superagent的功能,使其可以手动指定编码功能。
- 安装
$ npm i superagent-charset
- 使用
使用.charset(encoding)
方法,就可以指定编码,详细如下:
var assert = require('assert');
var request = require('superagent-charset');
request
.get('http://www.sohu.com/')
.charset('gbk')
.end(function(err,res) {
assert(res.text.indexOf('搜狐') > -1);
});
潜在问题
到目前为止,仅仅是解决了我们如何设置编码的问题,但是通常我们在爬取网页的时候,都是动态爬取的,也就是说并不是人工来指定网页的编码,那么如何才能做到动态指定网页编码呢?可以这么来做:
- 动态获取网站编码
- 指定网站编码并爬去
如何动态获取网站编码呢?
为了浏览器能正常渲染网页信息,网站通常都会在设置meta charset信息
,如
<meta charset='utf-8'>
或者
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
我们可以写一个正则匹配规则,来匹配这段信息中的charset
内容来获取编码,如下:
var charset = "utf-8";
var arr = res.text.match(/<meta([^>]*?)>/g);
if (arr) {
arr.forEach(function (val) {
var match = val.match(/charset\s*=\s*(.+)\"/);
if (match && match[1]) {
if (match[1].substr(0, 1) == '"')match[1] = match[1].substr(1);
charset = match[1].trim();
}
})
}
当然,前提是我们需要将网页先爬下来。完整的代码如下:
parseUrl: function (url, callback) {
async.waterfall([
function (callback) { // 动态获取网站编码
superagent.get(url).end(function (err, res) {
var charset = "utf-8";
var arr = res.text.match(/<meta([^>]*?)>/g);
if (arr) {
arr.forEach(function (val) {
var match = val.match(/charset\s*=\s*(.+)\"/);
if (match && match[1]) {
if (match[1].substr(0, 1) == '"')match[1] = match[1].substr(1);
charset = match[1].trim();
}
})
}
callback(err, charset)
})
}, function (charset, callback) { // 内容爬取
superagent
.get(url)
.charset(charset)
.end(function (err, res) {
if (err) {
console.log(err);
callback(err);
return;
}
var model = {};
var $ = cheerio.load(res.text);
var title = _.trim($('title').text());
if (title.indexOf('-') > 0) {
var strs = _.split(title, '-');
model.title = _.trim(title.substr(0, title.lastIndexOf('-')));
model.source = _.trim(_.last(strs));
} else {
model.title = _.trim(title);
}
callback(err, model);
})
}
],
function (err, model) {
callback(err, model);
});
}
整体思路:
- 现将网页内容爬下来,动态获取编码
- 再用得到的编码再爬一次。
所以,弊端就是:同一个页面要爬两次!同一个页面要爬两次!同一个页面要爬两次!
谨慎使用!