維護WHLCCrawler:css
這個爬蟲以前跑不通的緣由:
1.以前的做者寫的工具類,裏面的重定向出現了問題,沒有重定向成功。
解決方案:
我從新聲明一個httpclient,不過用的仍是defaultHttpclient的方式,這個方式早已通過時了,可是我須要他前面操做而後獲取他的cookie,用最新的方式的話,所有都要大改,因此我就跟着他先用着過期的方法,把以前進行操做的cookie放進去。放進去之後,手動完成重定向,他返回302狀態後,在返回的response中取出header,在header中取出location,把location當作新的url了,用以前的parma再從新訪問一遍,若是返回的是301則重複上訴操做。html
HttpResponse res = client.execute(post);
int status = res.getStatusLine().getStatusCode();
if(res.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_TEMPORARILY){
Header[] header ;
header = res.getHeaders("Location");
String location = header[0].getValue();
HttpPost post2 = new HttpPost(location);
post2.setEntity(entity);
DefaultHttpClient client2 = httpClientProxy.generateClient();
client2.setCookieStore(httpClientProxy.getCookieStore());
HttpResponse res2 = client2.execute(post2);
int status2 = res2.getStatusLine().getStatusCode();
if(res2.getStatusLine().getStatusCode() == HttpStatus.SC_MOVED_PERMANENTLY){
Header[] header2 ;
header2 = res2.getHeaders("Location");
String location2 = header2[0].getValue();
HttpPost post3 = new HttpPost(location2);
post3.setEntity(entity);
DefaultHttpClient client3 = httpClientProxy.generateClient();
client3.setCookieStore(httpClientProxy.getCookieStore());
HttpResponse res3 = client3.execute(post3);
int status3 = res3.getStatusLine().getStatusCode();
routeScheduleResponse = EntityUtils.toString(res3.getEntity());
System.out.print(routeScheduleResponse);
}
}
複製代碼
2.返回的response是亂碼
解決方案:觀察response header裏面,他的contenttype是gzip,就說明了網站把數據進行了壓縮,咱們獲取到是壓縮過得數據,想要得到正確的數據,就必須解碼,解碼成utf-8。由於原做者是直接返回的String,因此我在他原工具類裏面,添加了一個判斷,判斷header裏面的contenttype是否爲gzip,是的話,就進行轉碼,不是的話,也不影響以前的功能。
轉碼實現方式:由於返回來的是String,先用inputStream輸入流來接收他,再傳進去gzip輸入流。bash
InputStream in = response.getEntity().getContent();
GZIPInputStream gzin = new GZIPInputStream(in);
InputStreamReader isr = new InputStreamReader(gzin,"utf-8");
StringBuilder buffer = new StringBuilder();
BufferedReader reader = null;
reader = new BufferedReader(isr);
String line = null;
while ((line = reader.readLine()) != null) {
buffer.append(line + "\n");
}
reader.close();
body = buffer.toString();
複製代碼
3.特定的por和特定的fnd不能返回正確的結果 解決方案:由於這個爬蟲以前的邏輯是,模擬輸入出發國家,模擬輸入出發城市,再模擬目的國家,而後把進行完這些操做的cookie傳給要進行submit操做的client就能返回正確的結果。而當進行模擬輸出出發國家時,他會返回默認的出發國家,若是咱們恰好給的數據就是這個默認的國家的話,就不用進行模擬出發城市的操做,而我以前是進行的,可能這個cookie就是錯的,他往下面執行,就不能獲取正確的結果。
因此我在進行模擬輸入出發城市的時候,會獲取默認城市,跟我要搜索的城市進行比較。cookie
private boolean checkFromCity(String response,String fromCity) {
// TODO Auto-generated method stub
Parser parser;
try {
parser = Parser.createParser(new String(response.getBytes(), encode_UTF8), encode_UTF8);
parser.setEncoding(parser.getEncoding());
String defaultOption = parserOptionNode(parser, CSS_OPTION_SELECTED, ATTRIBUTE_VALUE);
if(defaultOption.equals(fromCity)){
return true;
}else{
return false;
}
} catch (UnsupportedEncodingException e) {
throw new UnRetriableException(RoboticsException.TYPE_UNKNOWN, "parser defaultOption from search index page meet encoding error!", e);
} catch (ParserException e) {
throw new UnRetriableException(RoboticsException.TYPE_UNKNOWN, "parser defaultOption from search index page meet parser error!", e);
}
}
private String parserOptionNode(Parser parser, String css, String attribute) throws ParserException {
// TODO Auto-generated method stub
NodeList searchResultNodes = extractNodesByCss(parser, css);
if (null == searchResultNodes || searchResultNodes.size() < 1) {
throw new RetriableException(RoboticsException.TYPE_UNEXPECTED_RESPONSE, "Can not get " + css + " element from route search page!", null);
}
OptionTag inputTag = (OptionTag) searchResultNodes.elementAt(1);
String value = inputTag.getAttribute(attribute);
return value;
}
private NodeList extractNodesByCss(Parser parser, String css) throws ParserException {
parser.reset();
CssSelectorNodeFilter searchResultFilter = new CssSelectorNodeFilter(css);
NodeList searchResultNodes = parser.extractAllNodesThatMatch(searchResultFilter);
return searchResultNodes;
}
複製代碼
這裏學到一個很重要的東西,怎麼把頁面轉成可解析的html而後根據css的值來取value。
首先把response轉成parse,parse是一個HTML解析器。CssSelectorNodeFilter searchResultFilter = new CssSelectorNodeFilter(css);這一句至關於設置一個過濾,NodeList searchResultNodes = parser.extractAllNodesThatMatch(searchResultFilter);而後裝載,把符合條件的的節點放在NodeList中。而後我要的節點在索引1的位置,取出索引1的的值,我取得節點標籤是option,就用optionTag來接收,而後用.getAttribute(attribute);來獲取這個節點裏面的值,我要獲取的是他的value,因此atribute的值是value。app