superAgent 模块发 POST 请求的中文参数问题
发布于 7 年前 作者 hanzichi 5496 次浏览 来自 问答

做模拟登录,登录名是中文,然后 POST 的地址是 GBK 编码的,但是登录不成功,应该是中文参数的编码问题,看到一个用 request 模块的相似问题,https://cnodejs.org/topic/56d2e1c69f876b7e665857c9,最后用它的 write 方法解决,superAgent 貌似也有 write 方法, https://github.com/visionmedia/superagent/blob/v1.7.2/lib/node/index.js#L483,试了几次没能成功,求老司机指导下,谢谢!

26 回复

试了下 request 确实是可以的,想知道用 superAgent 能不能搞?

@magicdawn 求指导啊哥 …

@alsotang 唐大哥,貌似不是这个问题,传输的数据是已经编码了过的,具体情况和 https://cnodejs.org/topic/56d2e1c69f876b7e665857c9 一样,把参数写在 request 的 write() 里就没问题了

@hanzichi 把传输的数据用 gbk 编码,给你推荐的库就是做编码用的,可以指定 charset。

@magicdawn 这个 write 的方式,太难看了,我给差评

superagent.post('url')
.send({
  loginname: urlencode2('中文名', 'gbk')
})

@alsotang 我是抓了实际 POST 的包,然后直接把编码后的参数填上去的,如果直接写在 superAgent 的 send,一直报用户名出错,如果用 https://cnodejs.org/topic/56d2e1c69f876b7e665857c9 那样写,却是可以的,可能是因为那个帖子里说的 “用一段代码手工把中文转换成gb2312编码的字符串,但把转换过的字符串传到request的form中去后,request又会对其中的%编码为%25,所以也不行”

哈哈 @alsotang 没办法, 写在正常的参数里会被再 urlencode 一次

superagent 有啥问题…贴代码啊…

superagent.Request.prototype.send 还和 req content-type 有关系

@magicdawn 就是同样的问题,我试了下用 request 的 write 方法是可以的,能不能用 superAgent 解决?就像您说的 “写在正常的参数里会被再 urlencode 一次”,superAgent 正常的写法不行 。。用了下 superAgent 的 write,可能是姿势不对,文档也没找到 write 方法,求大神赐教 。。

const request = require('superagent')
const urlencode  = require('urlencode')
request.post(url)
  .write(urlencode('para=中文参数', 'gbk'))
  .end((err, res) => {
    // ...
  });

这样呢

superAgent 正常的写法不行 。。

正常写法?

用了下 superAgent 的 write,可能是姿势不对,文档也没找到 write 方法

贴代码啊

@magicdawn @hanzichi

superagent.post('url')
.send(
	urlencode2.stringify({loginname: '中文名'}, 'gbk') // this is a string
)


request{
	url: url,
	method: 'POST',
	body: urlencode2.stringify({loginname: '中文名'}, 'gbk')  // this is a string
}

百分号的问题,我大意了。不过 superagent 和 request 好像都有发送 raw body 的方式

@magicdawn

中文参数已经编码过了。

这样是 ok 的。

var request = require('request');
var iconv = require('iconv-lite');

var post_request =
  request
    .post({
      url: 'https://xx.com',
      headers: {
        'Content-Type': 'application/x-www-form-urlencoded',
        'Cookie': 'PHPSESSID=xx'
      },
      encoding: null  // 关键代码
    }, function (err, sres, body) {
      // gbk 页面乱码
      var html = iconv.decode(body, 'gb2312');
      console.log(html);
    });

// form data
post_request.write("a=xx&b=xx&c=xx");

这样报错(TypeError: superagent.post(…).set(…).set(…).write(…).end is not a functi on):

var superagent = require('superagent');

superagent
  .post('https://xx.com')
  .set("Content-Type", "application/x-www-form-urlencoded")
  .set("Cookie", "PHPSESSID=xxx")
  .write("a=xx&b=xx&c=xx")  // form data
  .end(function(err, sres) {
    fs.writeFileSync("test.txt", sres.text);
  });

求赐教大神

@hanzichi

sorry superagent.Request.prototype.write 返回不是 this https://github.com/visionmedia/superagent/blob/v2.3.0/lib/node/index.js#L320-L332

var superagent = require('superagent');
var req = superagent
  .post('https://xx.com')
  .set("Content-Type", "application/x-www-form-urlencoded")
  .set("Cookie", "PHPSESSID=xxx")
  
req.write("a=xx&b=xx&c=xx")  // form data

req.end(function(err, sres) {
  fs.writeFileSync("test.txt", sres.text);
});

@alsotang send 需要注意 content-type 和 send参数, 不同组合有不同的序列化策略 https://github.com/visionmedia/superagent/blob/v2.3.0/lib/request-base.js#L348-L365 不过 req.send(string) + application/x-www-form-urlencoded 也就啥都没干, 和 write 一样吧 不过既然 send 要去读代码, 要是我, 就直接 req._data = xxx 了 😂

嗯, superagent 里的 urlencode 操作发生在 qs.stringify, 以前总是纠结要不要手动 encodeURIComponent 😂

@alsotang superAgent 报错了," Cannot read property ‘charset’ of undefined" …

代码大概这样

var superagent = require('superagent');
var urlencode2 = require("urlencode2");

superagent
  .post('https://xx.com')
  .set("Content-Type", "application/x-www-form-urlencoded")
  .set("Cookie", "PHPSESSID=xxx")
  .send(urlencode2.stringify({username: 'xx'}, 'gbk'))
  .send({'checkCode': '8876'})
  .end(function(err, sres) {
    console.log(sres.text);
  });

@magicdawn 厉害阿!这样可以了!谢谢大大

原来你就是 superagent-charset 的作者阿,superagent-charset 很好用!

@magicdawn @alsotang 借宝地再请教两位大大一个问题,想做验证码自动识别,用的是这个库 https://github.com/naptha/tesseract.js,验证码是 PHP 生成的,如果我手动在浏览器中复制验证码这个图片,然后粘贴到本地,是可以识别的,如果用 Node 下载下来,就报错,图片看起来一模一样阿,直接打开这个验证码地址是乱码,图片下载用的代码如下,重命名为 png 格式的(粘贴下来的也是 png 格式的)。

// to download picture
function download(url, savePath) {
  var req = http.get(url, function(res){
    var binImage = '';
    res.setEncoding('binary');

    res.on('data', function(chunk){
      binImage += chunk;
    });

    res.on('end', function(){
      if (!binImage) {
        console.log('image data is null');
        return null;
      }

      fs.writeFile(savePath, binImage, 'binary', function(err){
        if (err) throw err;
        console.log('It\'s saved!'); // 文件被保存
      });
    });
  });
}

是不是哪里姿势有误?

其实中文问题各种乱码应该感谢 iconv / iconv-lite 哈利路亚…

@hanzichi 八成是 buffer 在 ondata 的相加问题。

https://npm.taobao.org/package/superagentparse

.parse(parse('buffer')) 的例子来抓取图片吧。

@alsotang 看不懂… 囧

回到顶部