美文网首页我的NodeJS学习之路(实践之路)技术干货
nodejs使用superagent爬取网站内容中文乱码的解决方

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

作者: Devid | 来源:发表于2016-02-29 17:17 被阅读3122次

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

    superagent-charset使用说明

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

    1. 安装
    $ npm i superagent-charset
    
    1. 使用
      使用.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);
      });
    

    潜在问题

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

    1. 动态获取网站编码
    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);
            });
    }
    

    整体思路:

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

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

    谨慎使用!

    相关文章

      网友评论

      • EricLee_5884:试了下,正确写法应该是:
        var charset = require('superagent-charset');
        var superagent = require('superagent');
        var request = charset(superagent);
        request
        .get('http://www.sohu.com/')
        .charset('gbk')
        .end(function(err,res) {
        assert(res.text.indexOf('搜狐') > -1);
        });
      • 写优雅:是啊,爬两次。superagent 可以获取到blob类型,通过二进制判断编码?然后再自己编码
      • c57dddf3b833:楼主你忘记写
        ```
        const charset = require('superagent-charset');
        const request = require('superagent');
        charset(request);
        ```

      本文标题:nodejs使用superagent爬取网站内容中文乱码的解决方

      本文链接:https://www.haomeiwen.com/subject/tdygkttx.html