HttpClient + Jsoup 模拟登陆,解析HTML,信息筛选(广工图书馆)

 

HttpClient + Jsoup 模拟登陆,解析HTML获取信息

最近在做一个校园综合Android客户端,主要是想把学校各类网站信息进行整合,放在一个平台上,供学校学生阅览。

思路如下:

拿广东工业大学图书馆网站作为一个例子

实现目标:用个人账号登陆图书馆并获取到个人借阅情况。

登陆地址 http://222.200.98.171:81/login.aspx

这里会用到Chrome的开发者工具(浏览器按F12可以开启)



 
 

打开登陆界面的源码,下面是源码中的form标签

Html代码 
  1. <form name="aspnetForm" method="post" action="login.aspx?ReturnUrl=%2fuser%2fuserinfo.aspx" onsubmit="javascript:return WebForm_OnSubmit();" id="aspnetForm">  
  2. <div>  
  3. <input type="hidden" name="__EVENTTARGET" id="__EVENTTARGET" value="" />  
  4. <input type="hidden" name="__EVENTARGUMENT" id="__EVENTARGUMENT" value="" />  
  5. <input type="hidden" name="__VIEWSTATE" id="__VIEWSTATE" value="/wEPDwULLTE0MjY3MDAxNzcPZBYCZg9kFgoCAQ8PFgIeCEltYWdlVXJsBRt+XGltYWdlc1xoZWFkZXJvcGFjNGdpZi5naWZkZAICDw8WAh4EVGV4dAUt5bm/5Lic5bel5Lia5aSn5a2m5Zu+5Lmm6aaG5Lmm55uu5qOA57Si57O757ufZGQCAw8PFgIfAQUcMjAxM+W5tDAz5pyIMDXml6UgIOaYn+acn+S6jGRkAgQPZBYEZg9kFgQCAQ8WAh4LXyFJdGVtQ291bnQCCBYSAgEPZBYCZg8VAwtzZWFyY2guYXNweAAM55uu5b2V5qOA57SiZAICD2QWAmYPFQMTcGVyaV9uYXZfY2xhc3MuYXNweAAM5YiG57G75a+86IiqZAIDD2QWAmYPFQMOYm9va19yYW5rLmFzcHgADOivu+S5puaMh+W8lWQCBA9kFgJmDxUDCXhzdGIuYXNweAAM5paw5Lmm6YCa5oqlZAIFD2QWAmYPFQMUcmVhZGVycmVjb21tZW5kLmFzcHgADOivu+iAheiNkOi0rWQCBg9kFgJmDxUDE292ZXJkdWVib29rc19mLmFzcHgADOaPkOmGkuacjeWKoWQCBw9kFgJmDxUDEnVzZXIvdXNlcmluZm8uYXNweAAP5oiR55qE5Zu+5Lmm6aaGZAIID2QWAmYPFQMbaHR0cDovL2xpYnJhcnkuZ2R1dC5lZHUuY24vAA/lm77kuabppobpppbpobVkAgkPZBYCAgEPFgIeB1Zpc2libGVoZAIDDxYCHwJmZAIBD2QWBAIDD2QWBAIBDw9kFgIeDGF1dG9jb21wbGV0ZQUDb2ZmZAIHDw8WAh8BZWRkAgUPZBYGAgEPEGRkFgFmZAIDDxBkZBYBZmQCBQ8PZBYCHwQFA29mZmQCBQ8PFgIfAQWlAUNvcHlyaWdodCAmY29weTsyMDA4LTIwMDkuIFNVTENNSVMgT1BBQyA0LjAxIG9mIFNoZW56aGVuIFVuaXZlcnNpdHkgTGlicmFyeS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuPGJyIC8+54mI5p2D5omA5pyJ77ya5rex5Zyz5aSn5a2m5Zu+5Lmm6aaGIEUtbWFpbDpzenVsaWJAc3p1LmVkdS5jbmRkZL5QuJMrEZz+0UxuTVpXZ/EaY5A4" />  
  6. </div>  
  7.   
  8. <script type="text/javascript">  
  9. //<![CDATA[ 
  10. var theForm = document.forms['aspnetForm']; 
  11. if (!theForm) { 
  12.     theForm = document.aspnetForm; 
  13. function __doPostBack(eventTarget, eventArgument) { 
  14.     if (!theForm.onsubmit || (theForm.onsubmit() != false)) { 
  15.         theForm.__EVENTTARGET.value = eventTarget; 
  16.         theForm.__EVENTARGUMENT.value = eventArgument; 
  17.         theForm.submit(); 
  18.     } 
  19. //]]>  
  20. </script>  
  21.   
  22.   
  23. <script src="/WebResource.axd?d=kbLQnwjf5uNQN4GcWRC5kD1rIySOzkR3uLyKE5xUO0j4Fa2lQPZwQlk_qYaspRXtlojncSBfRJNkA00qXOMQqsKd8WY1&amp;t=634751988274393221" type="text/javascript"></script>  
  24.   
  25.   
  26. <script src="/WebResource.axd?d=nsbO6ZJty6_6fuRufFNYnRiJ-xEoD0xQr70NX6g0v64gngATPLSnyyt7jyZkELLW6THXmh92_m0Y5TyvhES_-JroQeU1&amp;t=634751988274393221" type="text/javascript"></script>  
  27. <script type="text/javascript">  
  28. //<![CDATA[ 
  29. function WebForm_OnSubmit() { 
  30. if (typeof(ValidatorOnSubmit) == "function" && ValidatorOnSubmit() == false) return false; 
  31. return true; 
  32. //]]>  
  33. </script>  
  34.   
  35. <div>  
  36.   
  37.     <input type="hidden" name="__EVENTVALIDATION" id="__EVENTVALIDATION" value="/wEWBQKa7ezdCwKOmK5RApX9wcYGAsP9wL8JAqW86pcIaBhXmFYzd5pGDTk/afln2TfArPw=" />  
  38. </div>  
  39. <input name="ctl00$ContentPlaceHolder1$txtlogintype" type="hidden" id="ctl00_ContentPlaceHolder1_txtlogintype" value="0" />  
  40. <div id="Login" class="clearFix">  
  41.     <div class="LoginTitle">  
  42.         登录我的图书馆  
  43.     </div>  
  44.       
  45.       
  46.     <div class="LeftLogin">  
  47.             <div class="LoginDiv">  
  48.                   
  49.                 <div class="loginContent">  
  50.                     <div class="loginInfo">  
  51.                         <span class="leftInfo">图书证号:</span>  
  52.                         <span class="rightInfo">  
  53.                             <input name="ctl00$ContentPlaceHolder1$txtUsername_Lib" type="text" id="ctl00_ContentPlaceHolder1_txtUsername_Lib" class="txtInput" autocomplete="off" /><span id="ctl00_ContentPlaceHolder1_rfv_UserName_Lib" style="color:Red;display:none;">请输入证号</span>  
  54.                         </span>  
  55.                     </div>  
  56.                     <div class="loginInfo">  
  57.                         <span class="leftInfo">密&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;码:</span>  
  58.                         <span class="rightInfo">  
  59.                             <input name="ctl00$ContentPlaceHolder1$txtPas_Lib" type="password" id="ctl00_ContentPlaceHolder1_txtPas_Lib" class="txtInput" /><span id="ctl00_ContentPlaceHolder1_rfv_Password_Lib" style="color:Red;display:none;">请输入密码</span>  
  60.                         </span>  
  61.                     </div>  
  62.                     <div>  
  63.                         <span id="ctl00_ContentPlaceHolder1_lblErr_Lib"></span>  
  64.                     </div>  
  65.                     <div class="loginInfo">  
  66.                         <input type="submit" name="ctl00$ContentPlaceHolder1$btnLogin_Lib" value="登录" onclick="javascript:WebForm_DoPostBackWithOptions(new WebForm_PostBackOptions(&quot;ctl00$ContentPlaceHolder1$btnLogin_Lib&quot;, &quot;&quot;, true, &quot;&quot;, &quot;&quot;, false, false))" id="ctl00_ContentPlaceHolder1_btnLogin_Lib" class="btn" />  
  67.                         <input type="button" value="清空" onclick="rset()" class="btn"/>  
  68.                     </div>  
  69.                 </div>  
  70.             </div>  
  71.         </div>  
  72.         <div class="RightDescription">  
  73.         <img src="images/pin.gif" />  <br/>  
  74.         1.  如果您使用的是公共电脑,请在使用完毕后,务必退出登录,以保安全。<br />  
  75.         2.  首次登录,请先<a href="changepas.aspx">修改初始密码</a>。  
  76.         </div>  
  77.           
  78.           
  79.           
  80.       
  81.       
  82. </div>  
  83.   
  84. <script type="text/javascript">  
  85. //<![CDATA[ 
  86. var Page_Validators =  new Array(document.getElementById("ctl00_ContentPlaceHolder1_rfv_UserName_Lib"), document.getElementById("ctl00_ContentPlaceHolder1_rfv_Password_Lib")); 
  87. //]]>  
  88. </script>  
  89.   
  90. <script type="text/javascript">  
  91. //<![CDATA[ 
  92. var ctl00_ContentPlaceHolder1_rfv_UserName_Lib = document.all ? document.all["ctl00_ContentPlaceHolder1_rfv_UserName_Lib"] : document.getElementById("ctl00_ContentPlaceHolder1_rfv_UserName_Lib"); 
  93. ctl00_ContentPlaceHolder1_rfv_UserName_Lib.controltovalidate = "ctl00_ContentPlaceHolder1_txtUsername_Lib"; 
  94. ctl00_ContentPlaceHolder1_rfv_UserName_Lib.focusOnError = "t"; 
  95. ctl00_ContentPlaceHolder1_rfv_UserName_Lib.errormessage = "请输入证号"; 
  96. ctl00_ContentPlaceHolder1_rfv_UserName_Lib.display = "Dynamic"; 
  97. ctl00_ContentPlaceHolder1_rfv_UserName_Lib.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid"; 
  98. ctl00_ContentPlaceHolder1_rfv_UserName_Lib.initialvalue = ""; 
  99. var ctl00_ContentPlaceHolder1_rfv_Password_Lib = document.all ? document.all["ctl00_ContentPlaceHolder1_rfv_Password_Lib"] : document.getElementById("ctl00_ContentPlaceHolder1_rfv_Password_Lib"); 
  100. ctl00_ContentPlaceHolder1_rfv_Password_Lib.controltovalidate = "ctl00_ContentPlaceHolder1_txtPas_Lib"; 
  101. ctl00_ContentPlaceHolder1_rfv_Password_Lib.focusOnError = "t"; 
  102. ctl00_ContentPlaceHolder1_rfv_Password_Lib.errormessage = "请输入密码"; 
  103. ctl00_ContentPlaceHolder1_rfv_Password_Lib.display = "Dynamic"; 
  104. ctl00_ContentPlaceHolder1_rfv_Password_Lib.evaluationfunction = "RequiredFieldValidatorEvaluateIsValid"; 
  105. ctl00_ContentPlaceHolder1_rfv_Password_Lib.initialvalue = ""; 
  106. //]]>  
  107. </script>  
  108.   
  109.   
  110. <script type="text/javascript">  
  111. //<![CDATA[ 
  112.  
  113. var Page_ValidationActive = false; 
  114. if (typeof(ValidatorOnLoad) == "function") { 
  115.     ValidatorOnLoad(); 
  116.  
  117. function ValidatorOnSubmit() { 
  118.     if (Page_ValidationActive) { 
  119.         return ValidatorCommonOnSubmit(); 
  120.     } 
  121.     else { 
  122.         return true; 
  123.     } 
  124.         //]]>  
  125. </script>  
  126. </form>  

里面很多代码,我们要从中提取出我们登陆所需要的表单信息,input 和 select 这些标签都是作为登陆表单内容,这里只有input标签我们就提取它就好了,代码如下:

initLoginParmas(String userName,StringpassWord)和getLoginFormData(String url)两个方法

Java代码 
  1. /** 
  2.      * 初始化参数 
  3.      *  
  4.      * @param userName 
  5.      * @param passWord 
  6.      * @return 
  7.      * @throws ParseException 
  8.      * @throws IOException 
  9.      */  
  10.     public static List<NameValuePair> initLoginParmas(String userName,  
  11.             String passWord) throws ParseException, IOException {  
  12.         List<NameValuePair> parmasList = new ArrayList<NameValuePair>();  
  13.         HashMap<String, String> parmasMap = getLoginFormData(LoginUrl);  
  14.         Set<String> keySet = parmasMap.keySet();  
  15.   
  16.         for (String temp : keySet) {  
  17.             if (temp.contains("Username")) {  
  18.                 parmasMap.put(temp, userName);  
  19.             } else if (temp.contains("txtPas")) {  
  20.                 parmasMap.put(temp, passWord);  
  21.             }  
  22.         }  
  23.   
  24.         Set<String> keySet2 = parmasMap.keySet();  
  25.         System.out.println("表单内容:");  
  26.         for (String temp : keySet2) {  
  27.             System.out.println(temp + " = " + parmasMap.get(temp));  
  28.         }  
  29.         for (String temp : keySet2) {  
  30.             parmasList.add(new BasicNameValuePair(temp, parmasMap.get(temp)));  
  31.         }  
  32.   
  33.         // System.out.println("initParams \n" + parmasMap);  
  34.   
  35.         return parmasList;  
  36.   
  37.     }  
Java代码 
  1. /** 
  2.      * 获取登录表单input内容 
  3.      *  
  4.      * @param url 
  5.      * @return 
  6.      * @throws IOException 
  7.      * @throws ParseException 
  8.      */  
  9.     public static HashMap<String, String> getLoginFormData(String url)  
  10.             throws ParseException, IOException {  
  11.         Document document = Jsoup.parse(getHtml(url));  
  12.         Elements element1 = document.getElementsByTag("form");// 找出所有form表单  
  13.         Element element = element1.select("[method=post]").first();// 筛选出提交方法为post的表单  
  14.         Elements elements = element.select("input[name]");// 把表单中带有name属性的input标签取出  
  15.         HashMap<String, String> parmas = new HashMap<String, String>();  
  16.         for (Element temp : elements) {  
  17.             parmas.put(temp.attr("name"), temp.attr("value"));// 把所有取出的input,取出其name,放入Map中  
  18.         }  
  19.         return parmas;  
  20.     }  

最后表单结果是:

表单内容:

Java代码 
  1. ctl00$ContentPlaceHolder1$txtlogintype = 0  
  2. __VIEWSTATE = /wEPDwULLTE0MjY3MDAxNzcPZBYCZg9kFgoCAQ8PFgIeCEltYWdlVXJsBRt+XGltYWdlc1xoZWFkZXJvcGFjNGdpZi5naWZkZAICDw8WAh4EVGV4dAUt5bm/5Lic5bel5Lia5aSn5a2m5Zu+5Lmm6aaG5Lmm55uu5qOA57Si57O757ufZGQCAw8PFgIfAQUcMjAxM+W5tDAz5pyIMDXml6UgIOaYn+acn+S6jGRkAgQPZBYEZg9kFgQCAQ8WAh4LXyFJdGVtQ291bnQCCBYSAgEPZBYCZg8VAwtzZWFyY2guYXNweAAM55uu5b2V5qOA57SiZAICD2QWAmYPFQMTcGVyaV9uYXZfY2xhc3MuYXNweAAM5YiG57G75a+86IiqZAIDD2QWAmYPFQMOYm9va19yYW5rLmFzcHgADOivu+S5puaMh+W8lWQCBA9kFgJmDxUDCXhzdGIuYXNweAAM5paw5Lmm6YCa5oqlZAIFD2QWAmYPFQMUcmVhZGVycmVjb21tZW5kLmFzcHgADOivu+iAheiNkOi0rWQCBg9kFgJmDxUDE292ZXJkdWVib29rc19mLmFzcHgADOaPkOmGkuacjeWKoWQCBw9kFgJmDxUDEnVzZXIvdXNlcmluZm8uYXNweAAP5oiR55qE5Zu+5Lmm6aaGZAIID2QWAmYPFQMbaHR0cDovL2xpYnJhcnkuZ2R1dC5lZHUuY24vAA/lm77kuabppobpppbpobVkAgkPZBYCAgEPFgIeB1Zpc2libGVoZAIDDxYCHwJmZAIBD2QWBAIDD2QWBAIBDw9kFgIeDGF1dG9jb21wbGV0ZQUDb2ZmZAIHDw8WAh8BZWRkAgUPZBYGAgEPEGRkFgFmZAIDDxBkZBYBZmQCBQ8PZBYCHwQFA29mZmQCBQ8PFgIfAQWlAUNvcHlyaWdodCAmY29weTsyMDA4LTIwMDkuIFNVTENNSVMgT1BBQyA0LjAxIG9mIFNoZW56aGVuIFVuaXZlcnNpdHkgTGlicmFyeS4gIEFsbCByaWdodHMgcmVzZXJ2ZWQuPGJyIC8+54mI5p2D5omA5pyJ77ya5rex5Zyz5aSn5a2m5Zu+5Lmm6aaGIEUtbWFpbDpzenVsaWJAc3p1LmVkdS5jbmRkZL5QuJMrEZz+0UxuTVpXZ/EaY5A4  
  3. ctl00$ContentPlaceHolder1$txtPas_Lib =密码不告诉你  
  4. __EVENTVALIDATION = /wEWBQKa7ezdCwKOmK5RApX9wcYGAsP9wL8JAqW86pcIaBhXmFYzd5pGDTk/afln2TfArPw=  
  5. ctl00$ContentPlaceHolder1$txtUsername_Lib = 3110006527  
  6. ctl00$ContentPlaceHolder1$btnLogin_Lib = 登录  

接下来是要登陆获取权限也就是获取到Cookie

代码如下:

Java代码 
  1. /** 
  2.      * 图书馆登陆 
  3.      *  
  4.      * @param context 
  5.      * @return 返回登陆后的界面Html代码 
  6.      * @throws ClientProtocolException 
  7.      * @throws IOException 
  8.      */  
  9.     public static String login() throws ClientProtocolException, IOException {  
  10.         List<NameValuePair> parmasList = new ArrayList<NameValuePair>();  
  11.         parmasList = initLoginParmas("3110006527", "2787457");  
  12.         HttpPost post = new HttpPost(LoginUrl);  
  13.         post.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);  
  14.         // 阻止自动重定向,目的是获取第一个ResponseHeader的Cookie和Location  
  15.         post.setHeader("Content-Type",  
  16.                 "application/x-www-form-urlencoded;charset=gbk");  
  17.         // 设置编码为GBK  
  18.         post.setEntity(new UrlEncodedFormEntity(parmasList, "GBK"));  
  19.         HttpResponse response = new DefaultHttpClient().execute(post);  
  20.         cookie = response.getFirstHeader("Set-Cookie").getValue();  
  21.         // 取得cookie并保存起来  
  22.         // System.out.println("cookie= " + cookie);  
  23.         location = response.getFirstHeader("Location").getValue();  
  24.         // 重定向地址,目的是连接到主页  
  25.         mainUrl = Host + location;  
  26.         // 构建主页地址  
  27.         String html = getHtml(mainUrl);  
  28.         return html;  
  29.   
  30.     }  

登陆获取Cookie时候会遇到返回状态码是302,这个时候Post方法的话,系统会自动重定向到Location地址,这时候你看到的ResponseHeader已经不是你登陆后返回的那个了,而是你访问重定向地址时候返回的ResponseHeader,而cookie是含在登陆时候返回的ResponseHeader里面所以特别要注意添加语句

Java代码 
  1. post.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS,false);  

给Post设置参数,这样就会阻止重定向,从而可以获取Cookie和Location(为了访问主页界面)

Java代码 
  1. cookie =response.getFirstHeader("Set-Cookie").getValue();  

接下来需要做的是根据Location得到主页地址,用Jsoup去解析主页,分析出我的借书情况的页面地址

接下来我们访问其他网页的时候就需要用到cookie 了,所以在用post或者get方法的时候要调用addHeader()或者setHeader();把Cookie设置进去

Java代码 
  1. /** 
  2.  * 获取网页HTML源代码 
  3.  *  
  4.  * @param url 
  5.  * @return 
  6.  * @throws ParseException 
  7.  * @throws IOException 
  8.  */  
  9.   
  10. private static String getHtml(String url) throws ParseException,  
  11.         IOException {  
  12.     // TODO Auto-generated method stub  
  13.     HttpGet get = new HttpGet(url);  
  14.     if ("" != cookie) {  
  15.         get.addHeader("Cookie", cookie);  
  16.     }  
  17.     HttpResponse httpResponse = new DefaultHttpClient().execute(get);  
  18.     HttpEntity entity = httpResponse.getEntity();  
  19.     return EntityUtils.toString(entity);  
  20. }  

通过Chrome浏览器分析页面源码,可以看到该标签

Java代码 
  1. <a href="bookborrowed.aspx" >当前借阅情况和续借</a>  

bookborrowed.aspx  这一段就是我们需要的

获取代码如下:

Java代码 
  1. public static void getMyBorrowedBooks() {  
  2.         try {  
  3.             Document document = Jsoup.parse(login());  
  4.             Elements elements1 = document  
  5.                     .getElementsContainingOwnText("当前借阅情况和续借");// 通过text关键字找到所要的<a>标签  
  6.             String url = elements1.first().attr("href");  
  7.             borrowedBooksUrl = mainUrl.substring(0,  
  8.                     mainUrl.lastIndexOf("/") + 1) + url;// 取值和mainUrl进行拼凑组织借阅情况地址  
  9.             getBookBorrowedData(getHtml(borrowedBooksUrl));  
  10.   
  11.         } catch (IOException e) {  
  12.             // TODO Auto-generated catch block  
  13.             e.printStackTrace();  
  14.         }  
  15.     }  

       获取到借书情况的地址后,我们就去访问这个地址,获取源码。

我们所需要的事这部分的数据(只截取一部分):

Java代码 
  1. <tr>              
  2.            <td width="5%">  
  3.              
  4.              
  5.            续满  
  6.              
  7.              
  8.            </td>  
  9.            <td width="10%">2013-04-10</td>  
  10.            <td width="35%"><a href="../bookinfo.aspx?ctrlno=571892" target="_blank">编写高质量代码 [专著]:改善Java程序的151个建议=Writing solw Java cove:151 suggestons to improve your Java program/秦小波著</a></td>  
  11.            <td width="5%"> </td>  
  12.            <td width="8%">中文图书</td>  
  13.            <td width="7%">A2973844</td>  
  14.            <td width="10%">2012-12-05</td>  
  15.         </tr>  
  16.          
  17.        <tr>         

    通过下面代码  用Jsoup进行筛选         

Java代码 
  1. /** 
  2.      * 获取借书情况具体数据(List<BookEntity>) 
  3.      *  
  4.      * @param src 
  5.      * @return List<BookEntity> 
  6.      */  
  7.     private static List<BookEntity> getBookBorrowedData(String src) {  
  8.         List<BookEntity> data = new ArrayList<BookEntity>();  
  9.         Document document = Jsoup.parse(src);  
  10.         Element element = document.select("[id=borrowedcontent]").first()  
  11.                 .getElementsByTag("table").first();  
  12.         Elements elements2 = element.getElementsByTag("tr");  
  13.         for (Element temp2 : elements2) {  
  14.             Elements elements3 = temp2.getElementsByTag("td");  
  15.             BookEntity entity = new test().new BookEntity()  
  16.                     .setIsFullData(elements3.get(0).text())  
  17.                     .setData2Return(elements3.get(1).text())  
  18.                     .setName(elements3.get(2).text())  
  19.                     .setData2Borrowed(elements3.get(6).text());  
  20.             data.add(entity);  
  21.   
  22.         }  
  23.         data.remove(0);  
  24.         System.out.println("借书情况\n");  
  25.   
  26.         for (BookEntity temp : data) {  
  27.             System.out.println(temp.getName() + "\n" + temp.getData2Borrowed()  
  28.                     + "\n" + temp.getData2Return() + "\n"  
  29.                     + temp.getIsFullData());  
  30.         }  
  31.         return data;  
  32.   
  33.     }  

    最后打印出来结果是:

Java代码 
  1. 借书情况  
  2.   
  3. 编写高质量代码 [专著]:改善Java程序的151个建议=Writing solw Java cove:151 suggestons to improve your Java program/秦小波著  
  4. 2012-12-05  
  5. 2013-04-10  
  6. 续满  
  7. 疯狂Java [专著]:突破程序员基本功的16课/李刚编著  
  8. 2012-12-05  
  9. 2013-04-10  
  10. 续满  
  11. 程序员修炼之道 [专著]:从小工到专家=The pragmatic programmer:From journeyman to master:评注版/(美)Andrew Hunt,(美)David Thomas著;周爱民,蔡学镛评注  
  12. 2012-11-22  
  13. 2013-04-10  
  14. 续满  
  15. 重构:改善既有代码的设计=Refactoring:improving the design of existing code/(美)Martin Fowler著;熊节译  
  16. 2012-11-22  
  17. 2013-04-10  
  18. 续满  
  19. Android高薪之路 [专著]:Android程序员面试宝典/李宁编著  
  20. 2012-11-29  
  21. 2013-04-10  
  22. 续满  
  23. Android技术内幕 [专著]·系统卷=Android internals·System/杨丰盛著  
  24. 2012-12-04  
  25. 2013-04-10  
  26. 续满  
  27. 我编程, 我快乐 [专著]:程序员职业规划之道=The passionate programmer:creating a remarkable career in software development/(美) Chad Fowler著;于梦瑄译  
  28. 2013-01-17  
  29. 2013-04-17  
  30. 续满  
Java代码 
  1. <strong>完整代码:</strong>  
  2. package moniLogin;  
  3.   
  4. import java.io.IOException;  
  5. import java.util.ArrayList;  
  6. import java.util.HashMap;  
  7. import java.util.Iterator;  
  8. import java.util.List;  
  9. import java.util.Set;  
  10.   
  11. import org.apache.http.Header;  
  12. import org.apache.http.HeaderElement;  
  13. import org.apache.http.HttpEntity;  
  14. import org.apache.http.HttpResponse;  
  15. import org.apache.http.NameValuePair;  
  16. import org.apache.http.ParseException;  
  17. import org.apache.http.client.ClientProtocolException;  
  18. import org.apache.http.client.entity.UrlEncodedFormEntity;  
  19. import org.apache.http.client.methods.HttpGet;  
  20. import org.apache.http.client.methods.HttpPost;  
  21. import org.apache.http.client.params.ClientPNames;  
  22. import org.apache.http.impl.client.DefaultHttpClient;  
  23. import org.apache.http.message.BasicNameValuePair;  
  24. import org.apache.http.util.EntityUtils;  
  25. import org.jsoup.Jsoup;  
  26. import org.jsoup.nodes.Document;  
  27. import org.jsoup.nodes.Element;  
  28. import org.jsoup.select.Elements;  
  29.   
  30. public class test {  
  31.     private static String LoginUrl = "http://222.200.98.171:81/login.aspx";  
  32.     private static String Host = "http://222.200.98.171:81";  
  33.     private static String mainUrl = "";  
  34.     private static String borrowedBooksUrl = "";  
  35.     private static String cookie = "";  
  36.     private static String location = "";  
  37.   
  38.     /** 
  39.      * @param args 
  40.      */  
  41.     public static void main(String[] args) {  
  42.         // TODO Auto-generated method stub  
  43.         getMyBorrowedBooks();  
  44.     }  
  45.   
  46.     public static void getMyBorrowedBooks() {  
  47.         try {  
  48.             Document document = Jsoup.parse(login());  
  49.             Elements elements1 = document  
  50.                     .getElementsContainingOwnText("当前借阅情况和续借");// 通过text关键字找到所要的<a>标签  
  51.             String url = elements1.first().attr("href");  
  52.             borrowedBooksUrl = mainUrl.substring(0,  
  53.                     mainUrl.lastIndexOf("/") + 1) + url;// 取值和mainUrl进行拼凑组织借阅情况地址  
  54.             getBookBorrowedData(getHtml(borrowedBooksUrl));  
  55.   
  56.         } catch (IOException e) {  
  57.             // TODO Auto-generated catch block  
  58.             e.printStackTrace();  
  59.         }  
  60.     }  
  61.   
  62.     /** 
  63.      * 获取借书情况具体数据(List<BookEntity>) 
  64.      *  
  65.      * @param src 
  66.      * @return List<BookEntity> 
  67.      */  
  68.     private static List<BookEntity> getBookBorrowedData(String src) {  
  69.         List<BookEntity> data = new ArrayList<BookEntity>();  
  70.         Document document = Jsoup.parse(src);  
  71.         Element element = document.select("[id=borrowedcontent]").first()  
  72.                 .getElementsByTag("table").first();  
  73.         Elements elements2 = element.getElementsByTag("tr");  
  74.         for (Element temp2 : elements2) {  
  75.             Elements elements3 = temp2.getElementsByTag("td");  
  76.             BookEntity entity = new test().new BookEntity()  
  77.                     .setIsFullData(elements3.get(0).text())  
  78.                     .setData2Return(elements3.get(1).text())  
  79.                     .setName(elements3.get(2).text())  
  80.                     .setData2Borrowed(elements3.get(6).text());  
  81.             data.add(entity);  
  82.   
  83.         }  
  84.         data.remove(0);  
  85.         System.out.println("借书情况\n");  
  86.   
  87.         for (BookEntity temp : data) {  
  88.             System.out.println(temp.getName() + "\n" + temp.getData2Borrowed()  
  89.                     + "\n" + temp.getData2Return() + "\n"  
  90.                     + temp.getIsFullData());  
  91.         }  
  92.         return data;  
  93.   
  94.     }  
  95.   
  96.     /** 
  97.      * 图书馆登陆 
  98.      *  
  99.      * @param context 
  100.      * @return 返回登陆后的界面Html代码 
  101.      * @throws ClientProtocolException 
  102.      * @throws IOException 
  103.      */  
  104.     public static String login() throws ClientProtocolException, IOException {  
  105.         List<NameValuePair> parmasList = new ArrayList<NameValuePair>();  
  106.         parmasList = initLoginParmas("3110006527", "密码不告诉你");  
  107.         HttpPost post = new HttpPost(LoginUrl);  
  108.         post.getParams().setParameter(ClientPNames.HANDLE_REDIRECTS, false);  
  109.         // 阻止自动重定向,目的是获取第一个ResponseHeader的Cookie和Location  
  110.         post.setHeader("Content-Type",  
  111.                 "application/x-www-form-urlencoded;charset=gbk");  
  112.         // 设置编码为GBK  
  113.         post.setEntity(new UrlEncodedFormEntity(parmasList, "GBK"));  
  114.         HttpResponse response = new DefaultHttpClient().execute(post);  
  115.         cookie = response.getFirstHeader("Set-Cookie").getValue();  
  116.         // 取得cookie并保存起来  
  117.         // System.out.println("cookie= " + cookie);  
  118.         location = response.getFirstHeader("Location").getValue();  
  119.         // 重定向地址,目的是连接到主页  
  120.         mainUrl = Host + location;  
  121.         // 构建主页地址  
  122.         String html = getHtml(mainUrl);  
  123.         return html;  
  124.   
  125.     }  
  126.   
  127.     /** 
  128.      * 获取网页HTML源代码 
  129.      *  
  130.      * @param url 
  131.      * @return 
  132.      * @throws ParseException 
  133.      * @throws IOException 
  134.      */  
  135.   
  136.     private static String getHtml(String url) throws ParseException,  
  137.             IOException {  
  138.         // TODO Auto-generated method stub  
  139.         HttpGet get = new HttpGet(url);  
  140.         if ("" != cookie) {  
  141.             get.addHeader("Cookie", cookie);  
  142.         }  
  143.         HttpResponse httpResponse = new DefaultHttpClient().execute(get);  
  144.         HttpEntity entity = httpResponse.getEntity();  
  145.         return EntityUtils.toString(entity);  
  146.     }  
  147.   
  148.     /** 
  149.      * 初始化参数 
  150.      *  
  151.      * @param userName 
  152.      * @param passWord 
  153.      * @return 
  154.      * @throws ParseException 
  155.      * @throws IOException 
  156.      */  
  157.     public static List<NameValuePair> initLoginParmas(String userName,  
  158.             String passWord) throws ParseException, IOException {  
  159.         List<NameValuePair> parmasList = new ArrayList<NameValuePair>();  
  160.         HashMap<String, String> parmasMap = getLoginFormData(LoginUrl);  
  161.         Set<String> keySet = parmasMap.keySet();  
  162.   
  163.         for (String temp : keySet) {  
  164.             if (temp.contains("Username")) {  
  165.                 parmasMap.put(temp, userName);  
  166.             } else if (temp.contains("txtPas")) {  
  167.                 parmasMap.put(temp, passWord);  
  168.             }  
  169.         }  
  170.   
  171.         Set<String> keySet2 = parmasMap.keySet();  
  172.         System.out.println("表单内容:");  
  173.         for (String temp : keySet2) {  
  174.             System.out.println(temp + " = " + parmasMap.get(temp));  
  175.         }  
  176.         for (String temp : keySet2) {  
  177.             parmasList.add(new BasicNameValuePair(temp, parmasMap.get(temp)));  
  178.         }  
  179.   
  180.         // System.out.println("initParams \n" + parmasMap);  
  181.   
  182.         return parmasList;  
  183.   
  184.     }  
  185.   
  186.     /** 
  187.      * 获取登录表单input内容 
  188.      *  
  189.      * @param url 
  190.      * @return 
  191.      * @throws IOException 
  192.      * @throws ParseException 
  193.      */  
  194.     public static HashMap<String, String> getLoginFormData(String url)  
  195.             throws ParseException, IOException {  
  196.         Document document = Jsoup.parse(getHtml(url));  
  197.         Elements element1 = document.getElementsByTag("form");// 找出所有form表单  
  198.         Element element = element1.select("[method=post]").first();// 筛选出提交方法为post的表单  
  199.         Elements elements = element.select("input[name]");// 把表单中带有name属性的input标签取出  
  200.         HashMap<String, String> parmas = new HashMap<String, String>();  
  201.         for (Element temp : elements) {  
  202.             parmas.put(temp.attr("name"), temp.attr("value"));// 把所有取出的input,取出其name,放入Map中  
  203.         }  
  204.         return parmas;  
  205.     }  
  206.   
  207.     class BookEntity {  
  208.         /** 
  209.          * 书名 
  210.          *  
  211.          */  
  212.         private String name;  
  213.         /** 
  214.          * 可借数 
  215.          */  
  216.         private String leandableNum;  
  217.         /** 
  218.          * 索引号 
  219.          */  
  220.         private String callNumber;  
  221.         /** 
  222.          * 作者 
  223.          */  
  224.         private String writer;  
  225.         /** 
  226.          * 出版社 
  227.          */  
  228.         private String publisher;  
  229.         /** 
  230.          * 还书时间 
  231.          */  
  232.         private String data2Return;  
  233.         /** 
  234.          * 借书时间 
  235.          */  
  236.         private String data2Borrowed;  
  237.         /** 
  238.          * 是否续满 
  239.          */  
  240.         private String isFullData;  
  241.   
  242.         public BookEntity() {  
  243.   
  244.         }  
  245.   
  246.         public String getName() {  
  247.             return name;  
  248.         }  
  249.   
  250.         public String getLeandableNum() {  
  251.             return leandableNum;  
  252.         }  
  253.   
  254.         public String getCallNumber() {  
  255.             return callNumber;  
  256.         }  
  257.   
  258.         public String getWriter() {  
  259.             return writer;  
  260.         }  
  261.   
  262.         public String getPublisher() {  
  263.             return publisher;  
  264.         }  
  265.   
  266.         public BookEntity setName(String name) {  
  267.             this.name = name;  
  268.             return this;  
  269.         }  
  270.   
  271.         public BookEntity setLeandableNum(String leandableNum) {  
  272.             this.leandableNum = leandableNum;  
  273.             return this;  
  274.         }  
  275.   
  276.         public BookEntity setCallNumber(String callNumber) {  
  277.             this.callNumber = callNumber;  
  278.             return this;  
  279.         }  
  280.   
  281.         public BookEntity setWriter(String writer) {  
  282.             this.writer = writer;  
  283.             return this;  
  284.         }  
  285.   
  286.         public BookEntity setPublisher(String publisher) {  
  287.             this.publisher = publisher;  
  288.             return this;  
  289.         }  
  290.   
  291.         public String getData2Return() {  
  292.             return data2Return;  
  293.         }  
  294.   
  295.         public String getData2Borrowed() {  
  296.             return data2Borrowed;  
  297.         }  
  298.   
  299.         public String getIsFullData() {  
  300.             return isFullData;  
  301.         }  
  302.   
  303.         public BookEntity setData2Return(String data2Return) {  
  304.             this.data2Return = data2Return;  
  305.             return this;  
  306.         }  
  307.   
  308.         public BookEntity setData2Borrowed(String data2Borrowed) {  
  309.             this.data2Borrowed = data2Borrowed;  
  310.             return this;  
  311.         }  
  312.   
  313.         public BookEntity setIsFullData(String isFullData) {  
  314.             this.isFullData = isFullData;  
  315.             return this;  
  316.         }  
  317.   
  318.     }  
  319.   
  320. }  

    关于Jsoup怎么使用这里就不详细说了,

    详细请查阅这个网站:http://www.open-open.com/jsoup/

原文地址:https://www.cnblogs.com/chenchuangfeng/p/2987334.html