nodejs使用superagent爬取网站内容中文乱码的解决方法

2019-06-13 14:38:25 浏览数 (1)

使用superagent爬取网站内容,当网页编码不是utf-8编码时,中文就会返回乱码,原因是superagent只支持utf-8的网页编码,我们可以使用其扩展的一个npm模块superagent-charset

superagent-charset使用说明

superagent-charset扩展了superagent的功能,使其可以手动指定编码功能。

  1. 安装
代码语言:javascript复制
$ npm i superagent-charset
  1. 使用 使用.charset(encoding)方法,就可以指定编码,详细如下:
代码语言:javascript复制
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);
  });

潜在问题

到目前为止,仅仅是解决了我们如何设置编码的问题,但是通常我们在爬取网页的时候,都是动态爬取的,也就是说并不是人工来指定网页的编码,那么如何才能做到动态指定网页编码呢?可以这么来做:

  1. 动态获取网站编码
  2. 指定网站编码并爬去

如何动态获取网站编码呢? 为了浏览器能正常渲染网页信息,网站通常都会在设置meta charset信息,如

代码语言:javascript复制
<meta charset='utf-8'>

或者

代码语言:javascript复制
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"/>

我们可以写一个正则匹配规则,来匹配这段信息中的charset内容来获取编码,如下:

代码语言:javascript复制
var charset = "utf-8";
var arr = res.text.match(/<meta([^>]*?)>/g);
if (arr) {
    arr.forEach(function (val) {
        var match = val.match(/charsets*=s*(. )"/);
        if (match && match[1]) {
            if (match[1].substr(0, 1) == '"')match[1] = match[1].substr(1);
            charset = match[1].trim();
        }
    })
}

当然,前提是我们需要将网页先爬下来。完整的代码如下:

代码语言:javascript复制
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(/charsets*=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);
        });
}

整体思路:

  1. 现将网页内容爬下来,动态获取编码
  2. 再用得到的编码再爬一次。

所以,弊端就是:同一个页面要爬两次!同一个页面要爬两次!同一个页面要爬两次!

谨慎使用!

0 人点赞