node爬虫之gbk网页中文乱码解决方案
之前在用node做爬虫时碰到的中文乱码问题一直没有解决,今天整理下备忘。(PS:网上一些解决方案都已经不行了)
中文乱码具体是指用node请求gbk编码的网页,无法正确获取网页中的中文(需要转码),"gbk"和"网页中的中文"两个条件是缺一不可的。可以获取utf-8编码的网页中的中文,也可以获取gbk编码网页中的英文数字等。
举个简单的例子。获取http://acm.hdu.edu.cn/statistic.php?pid=1000排名第一的答案的username,是为"极光炫影"。刷刷刷写下如下代码:
varcheerio=require(''cheerio'')
,superagent=require(''superagent'')
,express=require(''express'');
varurl=''http://acm.hdu.edu.cn/statistic.php?pid=1000'';
varapp=express();
app.get(''/'',function(req,res,next){
superagent.get(url)
.end(function(err,sres){
varhtml=sres.text;
var$=cheerio.load(html,{decodeEntities:false});
varans=$(''.table_texttda'').eq(0).html();
res.send(ans);
});
});
app.listen(3000,function(){
console.log(''appislisteningatport3000'');
});
得到了乱码,如下:
???????
如何获取正确的中文呢?这里提供几个解决方案应急(不关心原理,只是为了应急)。
方法一:
使用superagent-charset模块(2016-08-26:如出错,请使用0.1.1版本)。
varcheerio=require(''cheerio'')
,superagent=require(''superagent-charset'')
,express=require(''express'');
varurl=''http://acm.hdu.edu.cn/statistic.php?pid=1000'';
varapp=express();
app.get(''/'',function(req,res,next){
superagent.get(url)
.charset(''gbk'')
.end(function(err,sres){
varhtml=sres.text;
var$=cheerio.load(html,{decodeEntities:false});
varans=$(''.table_texttda'').eq(0).html();
res.send(ans);
});
});
app.listen(3000,function(){
console.log(''appislisteningatport3000'');
});
使用非常简单,只需要引入superagent-charset模块,且在链式调用时加入charset参数即可。superagent-charset模块包括了superAgent模块以及iconv-lite模块。源码可以参考Github。
方法二:
直接用iconv-lite模块进行转码。
iconv-lite是一个进行编码转换的模块(node默认编码utf-8)。需要decode的编码必须是Buffer类型。
用http模块:
http.get(url,function(sres){
varchunks=[];
sres.on(''data'',function(chunk){
chunks.push(chunk);
});
sres.on(''end'',function(){
//将二进制数据解码成gb2312编码数据
varhtml=iconv.decode(Buffer.concat(chunks),''gb2312'');
var$=cheerio.loadwww.wang027.com(html,{decodeEntities:false});
varans=$(''.table_texttda'').eq(0).html();
res.send(ans);
});
});
用request模块:
request({
url:url,
encoding:null//关键代码
},function(err,sres,body){
varhtml=iconv.decode(body,''gb2312'')
var$=cheerio.load(html,{decodeEntities:false});
varans=$(''.table_texttda'').eq(0).html();
res.send(ans);
});
用iconv进行decode传入的参数必须是Buffer。
encoding-EncodingtobeusedonsetEncodingofresponsedata.Ifnull,thebodyisreturnedasaBuffer.Anythingelse(includingthedefaultvalueofundefined)willbepassedastheencowww.baiyuewang.netdingparametertotoString()(meaningthisiseffectivelyutf8bydefault).(Note:ifyouexpectbinarydata,youshouldsetencoding:null.)
iconv-lite模块能配合http模块以及request模块使用,却不能直接和superAgent模块使用。因为superAgent是以utf8去取数据,然后再用iconv转也是不行的。页面是gbk编码的,sres.text已经是decode过了的结果,也就是说它已经被转换成utf8了,再转换成buffer出来的结果必须是不正确的。
|
|