Android實現正方系統的登錄以及課程表,成績獲取和空課室的查詢(二)

      上篇說了怎麼實現登錄的原理以及實現,接下來就是實現如何獲得課程表,成績以及空課室的信息了。其實原理很簡單,如果你真的有認真看上一篇的登錄實現步驟的話,其實很快就會得到結果。

       因爲原理都差不多,這裏我只說如何獲取課程表的信息,因爲其他的功能都和這個功能的數據獲取差不多。

      那麼下面就來進行對課程表的獲取把!

      登錄正方教務系統,然後點擊"學生個人課表",我們可以看到以下這個界面

    

   我們這時候就要用到上篇所教的HttpWatch進行抓包,注意要在點擊"學生個人課表"進行Record,接下來我們就會獲得以下信息

    

    點擊這個post請求,我們可以看到

     

    是不是覺得很熟悉,沒錯,這個就是正方教務系統獲取特定數據所需要的參數,所以按照我們之前那樣把這些參數都加入到post中就可以得到對應的數據

     那麼我們看看我們究竟會得到什麼數據?

    

   

    之前沒碰過html的人可能會驚呆了,這究竟是什麼東西?如果覺得看到這個不知道是什麼,請自己看下html,這裏就不說了。

    現在我們看上去可以看到我們的信息在裏面了,但是裏面夾雜着很多我們不需要的東西,那我們究竟要怎麼獲取到我們需要的數據?

    在我接觸java爬蟲的時候,我也不知道究竟要怎麼處理下載下來的html,但是有一天看到了hongyang大神的博客,學習了基本的java爬蟲以及如何獲取裏面的信息,真的

    覺得收益無窮,也是因爲看了他的博客,我纔會開啓了這幾個信息對java爬蟲的興趣,並進行對學校新聞的爬取,當然也包括這個。

    所以如果這裏看完之後覺得對html的數據解析不夠明白,可以看一下hongyang大神的博客學習學習。


    說了這麼多廢話,那麼究竟怎麼才能獲取到html中的特定數據呢?沒錯,就是jsoup。通過jsoup進行html的解析。其實通過jsoup進行對html進行解析沒什麼難度,難度只是

在於你要分析你下載下來的html,然後根據一些標籤的特點或者規律進行適當的解析,這是我在實現解析時候的越到的一個大困難。無疑,解析我學校的課程表真的很痛苦,因爲它有些格式不是很好,所以解析的時候我儘量要避免。

     下面來說一下究竟怎麼解析html:

      




public class ExtractService
{
	/**
	 * @param rule
	 * @return
	 */
	public static List<NewsInfo> extract(Rule rule)
	{

		// 進行對rule的必要校驗
		validateRule(rule);

		List<NewsInfo> datas = new ArrayList<NewsInfo>();<span style="font-family: Arial, Helvetica, sans-serif;"> </span>

		NewsInfo data = null;
		try
		{
			/**
			 * 解析rule
			 */
			String url = rule.getUrl();
			String[] params = rule.getParams();
			String[] values = rule.getValues();
			String resultTagName = rule.getResultTagName();
			int type = rule.getType();
			int requestType = rule.getRequestMoethod();

			
			List<NameValuePair> params1 = null;
			if (params != null)
			{ 
				params1=new ArrayList<NameValuePair>();
				for (int i = 0; i < params.length; i++)
				{
					NameValuePair nameValuePair=new BasicNameValuePair(params[i], values[i]);
					params1.add(nameValuePair);
				}
			}
			Document doc=null;
			if(params1!=null){
			String html=BaseApplication.getSearchHtml(url, params1);
			 doc=Jsoup.parse(html);                              //這裏解析html,獲取到<span style="font-family: Arial, Helvetica, sans-serif;">Document </span>

			}else{
				String html=BaseApplication.getHtml(url);
				 doc=Jsoup.parse(html);
			}
                       <span style="color:#ff0000;">//這以上的代碼只是爲了獲取html,關鍵代碼就只有一句(<span style="font-family: Arial, Helvetica, sans-serif;">doc=Jsoup.parse(html); )這句,重點是在下面</span></span>

			
			//處理返回數據
			Elements results = new Elements();
			switch (type)            //我們可以看到html有很多class,id,selection等標籤,所以通過switch來選出你需要獲得的標籤,然後獲取到你所指定的那個範圍,這樣就更進一步忽略掉沒用的信息了,這裏需要自己看下網頁源碼理解下,尤其對html不熟的。
			{
			case Rule.CLASS:
				results = doc.getElementsByClass(resultTagName);
				break;
			case Rule.ID:
				Element result = doc.getElementById(resultTagName);
				results.add(result);
				break;
			case Rule.SELECTION:
				results = doc.select(resultTagName);
				break;
			default:
				//當resultTagName爲空時默認去body標籤
				if (TextUtil.isEmpty(resultTagName))
				{
					results = doc.getElementsByTag("body");
				}
			}
                        //以下就是對指定"body"範圍中的內容進行解析,每個網頁都不同,所以你要根據你自己需求去獲取
			for (Element result : results)
			{
				Elements links = result.getElementsByTag("p");
				
				for (int i = 0; i < links.size(); i++)
				{
					Element unit_ele = links.get(i);
					Element link = unit_ele.getElementsByTag("a").get(0);
					
					String content=link.text();
					String href = link.attr("href");
					String title = link.attr("title");
					

					Element h4_ele = unit_ele.getElementsByTag("span").get(0);
					String from = h4_ele.attr("title");
					Element h4_ele1 = unit_ele.getElementsByTag("span").get(1);
					String date = h4_ele1.text();
					
					data = new NewsInfo();
					data.setLinkHref(href);
					data.setTitle(title);
					data.setFrom(from);
					data.setDate(date);
					data.setContent(content);
					
					datas.add(data);
				}
			}

		} catch (IOException e)
		{
			e.printStackTrace();
		}

		return datas;
	}
	

	/**
	 * 對傳入的參數進行必要的校驗
	 */
	private static void validateRule(Rule rule)
	{
		String url = rule.getUrl();
		if (TextUtil.isEmpty(url))
		{
			throw new RuleException("url不能爲空?");
		}
		if (!url.startsWith("http://"))
		{
			throw new RuleException("url的格式不正確?");
		}

		if (rule.getParams() != null && rule.getValues() != null)
		{
			if (rule.getParams().length != rule.getValues().length)
			{
				throw new RuleException("參數的鍵值對個數不匹配!");
			}
		}

	}


}
public class Rule
{
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 鏈接
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private String url;


<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 參數集合
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private String[] params;
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 參數對應的�??
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private String[] values;


<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * 對返回的HTML,第�?次過濾所用的標籤,請先設置type
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private String resultTagName;


<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> * CLASS / ID / SELECTION
<span style="white-space:pre">	</span> * 設置resultTagName的類型,默認爲ID 
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private int type = ID ;
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>/**
<span style="white-space:pre">	</span> *GET / POST
<span style="white-space:pre">	</span> * 請求的類型,默認GET
<span style="white-space:pre">	</span> */
<span style="white-space:pre">	</span>private int requestMoethod = GET ; 
<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>public final static int GET = 0 ;
<span style="white-space:pre">	</span>public final static int POST = 1 ;
<span style="white-space:pre">	</span>


<span style="white-space:pre">	</span>public final static int CLASS = 0;
<span style="white-space:pre">	</span>public final static int ID = 1;
<span style="white-space:pre">	</span>public final static int SELECTION = 2;


<span style="white-space:pre">	</span>public Rule()
<span style="white-space:pre">	</span>{
<span style="white-space:pre">	</span>}


<span style="white-space:pre">	</span>
<span style="white-space:pre">	</span>public Rule(String url, String[] params, String[] values,
<span style="white-space:pre">			</span>String resultTagName, int type, int requestMoethod)
<span style="white-space:pre">	</span>{
<span style="white-space:pre">		</span>super();
<span style="white-space:pre">		</span>this.url = url;
<span style="white-space:pre">		</span>this.params = params;
<span style="white-space:pre">		</span>this.values = values;
<span style="white-space:pre">		</span>this.resultTagName = resultTagName;
<span style="white-space:pre">		</span>this.type = type;
<span style="white-space:pre">		</span>this.requestMoethod = requestMoethod;
<span style="white-space:pre">	</span>}
    上面只是想幫助你理解一下詳細的jsoup解析是怎樣的,接下來我放源碼上來把

   

/**
     * 查詢個人課表方法
     *                                                       
     * @param xnd
     * @param xqd
     * @throws ClientProtocolException
     * @throws IOException
     * @return 
     */
    public static  HashMap<String, HashMap<Integer, ArrayList<Course>>> queryStuCourse(String xnd, String xqd)
            throws ClientProtocolException, IOException {
    	 HttpClient client = new DefaultHttpClient();
    	
    	 
    	 int lastIndexOf = stuName.lastIndexOf("同學");
    	 if(lastIndexOf!=-1)
    	  stuName = stuName.substring(0, lastIndexOf);
    	  System.out.println(stuName);
   	  
        String newQueryStuCourseUrl = queryStuCourseUrl + stuNumber + "&xm="
                + stuName + queryStuCourseGnmkd;
        
        System.out.println(newQueryStuCourseUrl);
        
        String viewState = IOUtils.getViewState(newQueryStuCourseUrl, Cookie,
                mainUrl + stuNumber);
        HttpPost queryStuCoursePost = new HttpPost(newQueryStuCourseUrl);
        
        queryStuCoursePost.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);
        
        List<NameValuePair> stuCoursePair = new ArrayList<NameValuePair>();
        stuCoursePair.add(new BasicNameValuePair("__EVENTTARGET", "xqd"));
        stuCoursePair.add(new BasicNameValuePair("__EVENTARGUMENT", ""));
        stuCoursePair.add(new BasicNameValuePair("__VIEWSTATE", viewState));
        stuCoursePair.add(new BasicNameValuePair("xnd", xnd));
        stuCoursePair.add(new BasicNameValuePair("xqd", xqd));
        queryStuCoursePost.setHeader("Cookie", Cookie);
        queryStuCoursePost.setHeader("Referer", mainUrl + stuNumber);
        UrlEncodedFormEntity entitySource = new UrlEncodedFormEntity(
                stuCoursePair);
        queryStuCoursePost.setEntity(entitySource);
        
        HttpResponse responseStuCourse = client.execute(queryStuCoursePost);
        String html = IOUtils.getHtml(responseStuCourse.getEntity()
                .getContent(), "GB2312");
        Document docCourse = Jsoup.parse(html);
        Elements eleCourse = docCourse.select("td");
        
        HashMap<String, ArrayList<String>>hashMap=new HashMap<String, ArrayList<String>>();
        System.out.println("eleCourse.size()"+eleCourse.size()+"");
 //測試代碼       
//        for (Element element : eleCourse) {
//			System.out.println(element.text());
//		}
     以上是獲取課程表的源碼,後面的有些沒有放上去,原因是每個學校所得出結果都有所不同,所以你們自己根據自己學校進行數據的封裝吧,這裏就不一一敘說了,因爲

解析課程表的信息真的很坑,我不知是不是每個學校的數據都這樣,我覺得吧,還是你們親自動手會比較好。

     這次的博客就先這樣把,本人第一次寫實戰類的博客,覺得寫的不怎麼好,望見諒。這裏不貼出大量的代碼是因爲本人覺得其實原理都差不多,如果你看了上一篇的博客你就知道究竟是怎麼回事。再者因爲本人研究了java爬蟲兩個星期,覺得把,還是自己動手起來效果會好很多,所以打算貼出一些重要的代碼,其他的讓你們自行補充。

     望提點建議,本人將來還會打算寫一篇基於人臉識別的簽到系統,所以希望能寫好點。

    今天就到此爲止把。

       

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章