PHP8.1.21版本已发布
vue8.1.21版本已发布
jquery8.1.21版本已发布

node爬虫之gbk网页中文乱码解决方案_html/css_WEB-ITnose

原创
2016-06-21 08:58:42 1640浏览

之前在用 node 做爬虫时碰到的中文乱码问题一直没有解决,今天整理下备忘。(PS:网上一些解决方案都已经不行了)

中文乱码具体是指用 node 请求 gbk 编码的网页,无法正确获取网页中的中文(需要转码),"gbk" 和 "网页中的中文" 两个条件是缺一不可的。可以获取 utf-8 编码的网页中的中文,也可以获取 gbk 编码网页中的英文数字等。

举个简单的例子。获取 http://acm.hdu.edu.cn/statistic.php?pid=1000排名第一的答案的 username,是为 "极光炫影"。刷刷刷写下如下代码:

var cheerio = require('cheerio')  , superagent = require('superagent')  , express = require('express');var url = 'http://acm.hdu.edu.cn/statistic.php?pid=1000';var app = express();app.get('//m.sbmmt.com/m/', function (req, res, next) {  superagent.get(url)    .end(function (err, sres) {      var html = sres.text;      var $ = cheerio.load(html, {decodeEntities: false});      var ans = $('.table_text td a').eq(0).html();      res.send(ans);    });  });app.listen(3000, function () {  console.log('app is listening at port 3000');});

得到了乱码,如下:

������Ӱ

如何获取正确的中文呢?这里提供几个解决方案应急(不关心原理,只是为了应急)。

方法一:

使用 superagent-charset模块。

var cheerio = require('cheerio')  , superagent = require('superagent-charset')  , express = require('express');var url = 'http://acm.hdu.edu.cn/statistic.php?pid=1000';var app = express();app.get('//m.sbmmt.com/m/', function (req, res, next) {  superagent.get(url)    .charset('gbk')    .end(function (err, sres) {      var html = sres.text;      var $ = cheerio.load(html, {decodeEntities: false});      var ans = $('.table_text td a').eq(0).html();      res.send(ans);    });});app.listen(3000, function () {  console.log('app is listening at port 3000');});

使用非常简单,只需要引入 superagent-charset模块,且在链式调用时加入 charset 参数即可。superagent-charset 模块包括了 superAgent 模块以及 iconv-lite 模块。源码可以参考 Github。

方法二:

直接用 iconv-lite模块进行转码。

iconv-lite是一个进行编码转换的模块(node 默认编码 utf-8)。需要 decode 的编码必须是 Buffer类型。

  • 用 http模块:

    http.get(url, function(sres) {  var chunks = [];  sres.on('data', function(chunk) {    chunks.push(chunk);  });  sres.on('end', function() {    // 将二进制数据解码成 gb2312 编码数据    var html = iconv.decode(Buffer.concat(chunks), 'gb2312');    var $ = cheerio.load(html, {decodeEntities: false});    var ans = $('.table_text td a').eq(0).html();    res.send(ans);  });});
  • 用 request模块:

    request({  url: url,   encoding: null  // 关键代码}, function (err, sres, body) {  var html = iconv.decode(body, 'gb2312')  var $ = cheerio.load(html, {decodeEntities: false});  var ans = $('.table_text td a').eq(0).html();  res.send(ans);});

    用 iconv 进行 decode 传入的参数必须是 Buffer。

    encoding- Encoding to be used on setEncoding of responsedata. If null, the bodyis returned as a Buffer. Anything else ( including the default value of undefined ) will be passed as the encoding parameter to toString()(meaning this is effectively utf8by default). ( Note: if you expect binary data, you should set encoding: null.)

iconv-lite 模块能配合 http 模块以及 request 模块使用,却不能直接和 superAgent 模块使用。 因为 superAgent 是以 utf8 去取数据,然后再用 iconv 转也是不行的。页面是 gbk 编码的,sres.text 已经是 decode 过了的结果,也就是说它已经被转换成 utf8 了,再转换成 buffer 出来的结果必须是不正确的。

声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn核实处理。