前言
以前做过淘客开发,那时候高佣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++) {
//获取验证码图片url
String 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什么的 以后也不方便修改~
另外关于验证是滑块的也可以通过打码来解决的~我没去深究,有兴趣的可以自己尝试……