不仅仅限于java
- 前言
- 验证码识别
- 工具
- 分析
- 编码
- 数据演示
- 后记
前言
以前做过淘客开发,那时候高佣api很少,高佣的办法就是查询商品模拟转链为高佣,但是后来淘宝慢慢禁止了爬虫一直弹验证码,后来我就利用验证码识别成功扛过那段日子,大批淘宝工具商发布高佣接口,验证码识别也就没有用了。本文说的并不是指怎么利用图像去识别的技术,而是怎么突破淘宝的接口限制让爬虫可以获取信息。
验证码识别
你可以去各大验证码的打码平台识别或者自己写识别库。
以后如果我有时间可能会搭建一下验证码识别的接口~再说吧
工具
Google浏览器,Fiddler代理工具,IDEA(代码编写),验证码识别接口。
分析
- 当去模拟请求一个淘宝页面的时候,如果过于频繁会302转向到类似如下界面
- 分析一下提交的参数
可以看到checkcode 就是我们输入的数字,如果输入对了就会跳转到原url,否则将会继续请求验证码图片url,
关于其他参数和验证码图片的url都可以在这个验证HTM文本中找到。除了提交的checkcode(验证码)的需要自己输入,还有淘宝ua的算法比较难搞其他的参数本来在页面就是有的,经测试ua其实对验证码提交无影响,所以只需要识别验证码就可以啦。 - 输入正确的验证码就可以继续访问的原来的接口
编码
Java HTTP请求模块,个人最喜欢的~当然你也可以用httpckient等其他模块。
Requests is a http request lib with fluent api for java, inspired by the python request module. Requests requires JDK 1.7+.
https://github.com/hsiafan/requests
//首先访问原始接口resp = Requests.get(url2).headers(headersmap).send();result1 = resp.readToText();//如果获取的原始接口中内容为空 就表示淘宝限制了String createtime = getMiddleText.......//省略//仅仅识别五次,五次还不通过,就放弃本条数据for (int i = 0; i < 5 && StringUtils.isEmpty(createtime); i++) {//获取验证码图片urlString codeurl = "https:" + getMiddleText(result1, "<img id=\"checkcodeImg\" src=\"", "\"");//调用识别接口String code = getCode(codeurl);System.out.println("这是识别后的结果" + code);//获取页面其他参数Map<String, Object> map = getParamsMap(result1, code);//模拟手动输入验证码 提交数据(这个函数 我在下面会公开,因为涉及到一些坑)String coderes = queryCode(map, headersmap);createtime = getMiddleText(coderes, ....//省略}
拼接参数函数
这里说明一下,requests提交的时候默认会自动编码成utf8
public static Map getParamsMap(String text, String code) {text = text.replaceAll("amp;", "");Map<String, Object> map = new HashMap<String, Object>();try {Pattern pattern = Pattern.compile("<input type=\"hidden\" name=\"(.*?)\" value=\"(.*?)\"");Matcher matcher = pattern.matcher(text);//正则批量提取form中参数while (matcher.find()) {//URLEncoder.encode(matcher.group(2), "utf-8");map.put(matcher.group(1), matcher.group(2)); }//识别的验证码map.put("checkcode", code);//无影响map.put("ua", "");return map;} catch (Exception e) {e.printStackTrace();}return null;}
提交验证码参数,注意一定要用淘宝cookie。
/*验证码识别--提交识别结果*/public static String queryCode(Map<String, Object> map, Map headersMap) {RawResponse rawResponse = Requests.post("https://sec.taobao.com/query.htm").body(map).headers(headersMap).send();//代理模式 我一般是调试的时候结合Fiddler,这样就可以在Fiddler看到java请求,很方便找出模拟和实际的区别 // .proxy(Proxies.httpProxy("127.0.0.1", 8888))//打印响应头System.out.println(rawResponse.getHeaders().toString());String code = rawResponse.readToText();return code;}
数据演示
可以发现一般都是识别一次就可以获取到数据了,并不用识别5次,(当然这个更识别准确度有关~~~)
后记
使用resquests模块居然发现他默认编码utf8,导致我一直error。后来通过Http代理到FIddler查看请求才发现(Fiddler直接是抓不到调试的时候http数据包,所以只有手动代理才能发现)
提交验证码的时候需要淘宝cookie,不然返回过去也有问题
Java的正则写多行的话是真的难看啊~~~一堆的\n什么的 以后也不方便修改~
另外关于验证是滑块的也可以通过打码来解决的~我没去深究,有兴趣的可以自己尝试……