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爬虫两个星期,觉得把,还是自己动手起来效果会好很多,所以打算贴出一些重要的代码,其他的让你们自行补充。

     望提点建议,本人将来还会打算写一篇基于人脸识别的签到系统,所以希望能写好点。

    今天就到此为止把。

       

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