使用superagent爬取網(wǎng)站內(nèi)容,當網(wǎng)頁編碼不是utf-8
編碼時,中文就會返回亂碼苹祟,原因是superagent只支持utf-8的網(wǎng)頁編碼,我們可以使用其擴展的一個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);
});
潛在問題
到目前為止团赏,僅僅是解決了我們?nèi)绾卧O(shè)置編碼的問題箕般,但是通常我們在爬取網(wǎng)頁的時候,都是動態(tài)爬取的舔清,也就是說并不是人工來指定網(wǎng)頁的編碼丝里,那么如何才能做到動態(tài)指定網(wǎng)頁編碼呢?可以這么來做:
- 動態(tài)獲取網(wǎng)站編碼
- 指定網(wǎng)站編碼并爬去
如何動態(tài)獲取網(wǎng)站編碼呢体谒?
為了瀏覽器能正常渲染網(wǎng)頁信息杯聚,網(wǎng)站通常都會在設(shè)置meta charset信息
,如
<meta charset='utf-8'>
或者
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>
我們可以寫一個正則匹配規(guī)則抒痒,來匹配這段信息中的charset
內(nèi)容來獲取編碼幌绍,如下:
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();
}
})
}
當然,前提是我們需要將網(wǎng)頁先爬下來故响。完整的代碼如下:
parseUrl: function (url, callback) {
async.waterfall([
function (callback) { // 動態(tài)獲取網(wǎng)站編碼
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) { // 內(nèi)容爬取
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);
});
}
整體思路:
- 現(xiàn)將網(wǎng)頁內(nèi)容爬下來傀广,動態(tài)獲取編碼
- 再用得到的編碼再爬一次。
所以彩届,弊端就是:同一個頁面要爬兩次伪冰!同一個頁面要爬兩次!同一個頁面要爬兩次樟蠕!
謹慎使用贮聂!