成品展示:
(博主手残党)
完整成品:http://myspace123.qiniudn.com/456.html
源码:https://github.com/xcr1234/overwatch
在入坑前先看一下之前的博文吧!从爬取湖北某高校hub教务系统课表浅谈Java信息抓取的实现
暴雪爸爸在守望先锋的官网上提供了一个生涯数据的查询,可惜没有提供相关的API,“无法通过公开渠道自由抓到完整数据”。因此是通过模拟登陆、解析html的方式获取数据
1.开发环境
httpclient抓取页面数据
jsoup解析html
mozilla rhino执行js代码
2。抓包
使用fiddler抓包,暴雪的登录接口是
这里面的csrftoken和sessionTimeout在页面上有,useSrp、persistLogin、fp都是常量,password是占位符
主要需要解决的问题就是publicA(公钥)和clientEvidenceM1(凭据)
3.生成公钥和凭据
不用在意publicA(公钥)和clientEvidenceM1(凭据)的意义,这两个是从login.js的onSuccess方法中生成出来的。其中login.js使用了srp.js的对象SrpClientSession,直接使用rhino执行onSuccess的方法就行了。
(需要的moduls,generator等参数从一个csrf-token的api中获取)
由于srp.js很大,rhino执行时很慢,因此先用rhino compiler编译成srp.class文件,用PluginClassLoader动态加载进来执行。编译后的class是实现了Script接口的,它有一个public Object exec(Context cx, Scriptable scope);方法,用来执行自身。
4、附录
a.非常重要的设置
HttpClient的Cookie不正确,报invalid cookie header的错误。
RequestConfig.Builder builder = RequestConfig.custom(); builder.setCookieSpec(CookieSpecs.STANDARD); RequestConfig config = builder.build(); httpPost.setConfig(config); //httpGet.setConfig(config);
b.创建classloader时,应该使用AccessController.doPrivileged方法。
c.rhino的Context,Scope,Script应该在同一个线程中执行。
1 loginForm.csrfToken.val(e.csrf_token), this.password = this.inputPassword.val(), 2 3 this.srpClientSession = new SrpClientSession(e.modulus, e.generator, e.hash_function), 4 5 6 this.srpClientCredentials = this.srpClientSession.step1(e.username, this.password, e.salt, e.public_B), 7 8 null !== this.password && this.inputPassword.val(Array(this.password.length + 1).join(this.passwordFill)), 9 10 this.inputUseSrp.val("true"), 11 this.inputPublicA.val(this.srpClientCredentials.publicA.toString(16)), 12 13 this.inputClientEvidenceM1.val(this.srpClientCredentials.clientEvidenceM1.toString(16))
// 在原来的基础上加了var navigator = {}; 以免rhino报错 // https://github.com/xcr1234/overwatch/blob/master/src/main/resources/srp.js
5。问题
在登录成功后自动跳转(redirect)有问题,目前只能手动跳转