基於JAVA解決淘寶爬蟲限制
不僅僅限於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++) { //獲取驗證碼圖片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什麼的 以後也不方便修改~
另外關於驗證是滑塊的也可以通過打碼來解決的~我沒去深究,有興趣的可以自己嘗試……