爬蟲學習日記(八)

維護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

相關文章
相關標籤/搜索