前言

之前搞过几次模拟登录,都是模拟 post 后取到 cookie,之后便能用这个 cookie 愉快玩耍。这次碰到了验证码,其实只需手动登录一次,手动取到 cookie 后也能玩耍,不过 cookie 有效期不长,经常要换,十分麻烦。然后看到了这个库 tesseract.js,由于我们的验证码机器识别难度并不是很高,试了下出现 good case 概率还是非常高的,决定试下自动识别验证码登录。

验证码是用 PHP 生成的,指向一个 PHP 地址。原理不是很难,PHP 生成验证码图片,开启 Session(所以每次点击验证码切换图片,都会是一个新的 Session),然后把验证码数字记在 Session 数组中,当用户提交表单后,check 输入的验证码数字是否存在于 Session 数组中。

用的语言是 Node。之前想的非常简单,首先将验证码 down 下来,然后调用 tesseract.js 识别,最后模拟 post 后取到后续操作需要的 key cookie。

POST 中文参数问题

出现该问题需要满足两个条件:

  • 页面编码 GBK
  • POST 携带中文参数

模拟 post 有个参数 username 用的是中文,如果页面是 utf-8 编码应该没这个问题,就直接发送中文参数了,但是看实际请求中文参数被编码了,查了下 urlencode 这个包可以做类似的编码。将这个被编码后的参数填入发起模拟请求,报用户名错误,然后查到了 这个帖子,场景类似,同样是 gbk 编码页面的 post 携带了中文参数,我猜测原因也可能相同,被二次编码了。

但把转换过的字符串传到 request 的 form 中去后,request 又会对其中的 % 编码为 %25

用帖子里的方法可以解决:

  1. var request = require('request');
  2. var iconv = require('iconv-lite');
  3. var post_request = request
  4. .post({
  5. url: 'https://xx.com',
  6. headers: {
  7. 'Content-Type': 'application/x-www-form-urlencoded',
  8. 'Cookie': 'PHPSESSID=xx'
  9. },
  10. encoding: null // 关键代码
  11. }, function (err, sres, body) {
  12. // 解决返回页面乱码(gbk)
  13. var html = iconv.decode(body, 'gb2312');
  14. console.log(html);
  15. });
  16. // form data
  17. post_request.write("a=xx&b=xx&c=xx");

请求 gbk 页面会中文乱码,这里用了 iconv-lite 这个包,其他解决方法可以参考 node爬虫之gbk网页中文乱码解决方案

因为一直用的是 superAgent 这个模块,所以希望能在 superAgent 基础上解决这个问题,然后在 cnode 提了个 问题 ,最后也是解决了。

为了避免返回信息中文乱码,用了 superagent-charset 这个包:

  1. var superagent = require('superagent-charset');
  2. var req = superagent
  3. .post('https://xx.com')
  4. .set("Content-Type", "application/x-www-form-urlencoded")
  5. .set("Cookie", "PHPSESSID=xxx")
  6. .charset('gbk');
  7. // form data
  8. req.write("username=xx&password=xx&checkcode=xx");
  9. req.end(function(err, sres) {
  10. console.log(sres.text);
  11. });

验证码识别

以上问题解决后,PHPSESSID 这个 cookie 非常容易获取,模拟请求一次取 cookie 即可。手动在代码中输入浏览器中显示的验证码,模拟登录可以成功,然后取登录后的 cookie,确实也可以愉快玩耍,不过问题来了,验证码图片无法识别了!

昨天晚上试了下直接在登录页面右键复制下来验证码,然后用 tesseract.js 是可以解析的,但是用 Node down 下来的却不能解析,alsotang 大大说可能是 "buffer 在 ondata 的相加问题"。刚才试了下昨天手动保存验证码图片,成功解析的 case 也报错了,感觉是 tesseract.js 这个库还不是很成熟,过段时间再看看。

下载图片用的是这个函数:

  1. // to download picture
  2. function download(url, savePath) {
  3. var req = http.get(url, function(res){
  4. var binImage = '';
  5. res.setEncoding('binary');
  6. res.on('data', function(chunk){
  7. binImage += chunk;
  8. });
  9. res.on('end', function(){
  10. if (!binImage) {
  11. console.log('image data is null');
  12. return null;
  13. }
  14. fs.writeFile(savePath, binImage, 'binary', function(err){
  15. if (err) throw err;
  16. console.log('It\'s saved!'); // 文件被保存
  17. });
  18. });
  19. });
  20. }

对 Node 不熟,这个问题留坑以后待解决了。

问题解决过程中,除了上面的帖子,还在 v 站发了个帖子,如何模拟登录有验证码的网站?,FYI

「post中文参数问题」以及「验证码自动识别备忘」的更多相关文章

  1. 如何评价苹果中国官网 iOS 8 介绍页面的文案「开发者的大事、大快所有人心的大好事」?[转自知乎]

    在什么是「苹果式中文」答案中,小七得出了这个结论: 「苹果式中文」是指句子结构破碎,经常缺乏主语,滥用排比,顶真,偏正短语,和不恰当四字词的广告文体. (有关什么是苹果式中文,小七原来贴错地方了TAT ...

  2. Java的参数传递是「按值传递」还是「按引用传递」?

    JAVA传递的只有值,.传递的都是栈里的的值,只是有些栈里面的是值.有的是内存地址.(原文传递的都是栈里的的值有误,局部变量在栈中,成员变量在堆中,类变量(静态变量和常量)在方法区中,可以看做本文的变 ...

  3. 【微信小程序】开发实战 之 「配置项」与「逻辑层」

    微信小程序作为微信生态重要的一环,在实际生活.工作.商业中的应用越来越广泛.想学习微信小程序开发的朋友也越来越多,本文将在小程序框架的基础上就微信小程序项目开发所必需的基础知识及语法特点进行了详细总结 ...

  4. [转帖]详解shell脚本括号区别--$()、$「 」、$「 」 、$(()) 、「 」 、「[ 」]

    详解shell脚本括号区别--$().$「 」.$「 」 .$(()) .「 」 .「[ 」] 原创 波波说运维 2019-07-31 00:01:00 https://www.toutiao.com ...

  5. Git 执行 「fork 出来的仓库」和「最新版本的原仓库」内容同步更新

    当我们在 GitHub 上 fork 出一个仓库后,如果原仓库更新了,此时怎样才能保证我们 fork 出来的仓库和原仓库内容一致呢?我们一般关注的是仓库的 master(主干分支)的内容,通过以下步骤 ...

  6. FileUpload控件「批次上传 / 多档案同时上传」的范例--以「流水号」产生「变量名称」

    原文出處  http://www.dotblogs.com.tw/mis2000lab/archive/2013/08/19/multiple_fileupload_asp_net_20130819. ...

  7. Java的参数传递是「值传递」还是「引用传递」?

    关于Java传参时是引用传递还是值传递,一直是一个讨论比较多的话题. 有人说Java中只有值传递,也有人说值传递和引用传递都是存在的,比较容易让人产生疑问. 关于值传递和引用传递其实需要分情况看待. ...

  8. Linux 小知识翻译 - 「Unix」和「兼容Unix的OS」

    经常有人会问「Linux和Unix有什么区别?」,「Linux就是Unix吗?」. 回答一般都是「Linux是仿照Unix而开发的OS」,「Linux和Unix相似但不是一种OS」之类的. 关于「Li ...

  9. Linux 小知识翻译 - 「Linux」和「发行版」之间的关系

    「Linux」本来指的仅仅是内核.5年之前大多都是这么认为的,但是最近不这么说了. 最近一般都说「Linux」是个 OS,这里的OS,不仅仅是内核,而是指电脑的整体环境(除了内核,还包括一些外围的软件 ...

随机推荐

  1. 一个简单的webservice的demo(下)winform异步调用webservice

    绕了一大圈,又开始接触winform的项目来了,虽然很小吧.写一个winform的异步调用webservice的demo,还是简单的. 一个简单的Webservice的demo,简单模拟服务 一个简单 ...

  2. 自己手写的自动完成js类

    在web开发中,为了提高用户体验,会经常用到输入框的自动完成功能,不仅帮助用户进行快速输入,最重要的是帮助那些“记不全要输入什么”的用户进行选择.这个功能有很多插件已经实现了,为了适应项目的特殊需求, ...

  3. 扩展方法(C#)

    扩展方法使你能够向现有类型“添加”方法,而无需创建新的派生类型.重新编译或以其他方式修改原始类型.扩展方法是一种特殊的静态方法,但可以像扩展类型上的实例方法一样进行调用. 下面的示例为String添加 ...

  4. CLR via C# 摘要二:IL速记

    最简单的IL程序 .assembly test {} .method void Func() { .entrypoint ldstr "hello world" call void ...

  5. C#实现微信开发前奏

    不想废话,直接写了!因为是留给自己做随笔的,所以大神们看到别喷…… 1.必须有微信公众账号 2.你也可以申请测试微信号,链接给你   http://mp.weixin.qq.com/debug/cgi ...

  6. css全局格式化

    /*全局控制*/ body{margin:0;padding:0;font-size:14px;line-height:22px; height:auto; font-family:"微软雅 ...

  7. 【Spring】SpringMVC入门示例讲解

    目录结构: // contents structure [-] SpringMVC是什么 Spring MVC的设计原理 SpringMVC入门示例 1,复制Jar包 2,Web.xml文件 3,My ...

  8. kmdjs集成uglifyjs2打造极致的编程体验

    回顾 上篇文章大概展示了kmdjs0.1.x时期的编程范式: 如下面所示,可以直接依赖注入到function里, kmdjs.define('main',['util.bom','app.Ball', ...

  9. node-sass 在Mac中安装报错

    在做一个基于react项目要安装依赖的包时总是报一下错误 应该是node-sass的问题  找到官网下载跟我错误提示一样的文件也就是 darwin-x64-46 不同的系统不一样 修改为跟本地一样的名 ...

  10. IOS开发基础知识碎片-导航

    1:IOS开发基础知识--碎片1 a:NSString与NSInteger的互换 b:Objective-c中集合里面不能存放基础类型,比如int string float等,只能把它们转化成对象才可 ...