java实现的简单网页爬虫:Servlet + MySQL5.5(二)
在 java实现的简单网页爬虫:Servlet + MySQL5.5 进行了改善,将爬取的网址,进行分类保存。
<span style="font-size:14px;">/* * * @author Administrator * * 在JavaSpider 1.3 的基础上,对爬取的网址,进行分类存储 * * 1,把temp_url 临时网址,存储到临时表 temp_url 中; * 2,把target_url 目标网址,存储到目标表 target_url 中; * */</span>
项目中用到的所有文件,可以在资源里面下载 :
http://download.csdn.net/detail/reggergdsg/9406609
简单看一下效果图:
关键代码一:JavaSpider_2016/src/com/spider/servlet/SaveToDifferentDatabase_JavaSpider_1_5_Servlet.java servlet控制器类
package com.spider.servlet; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.spider.Model.Target_url; import com.spider.Model.Temp_url; <span style="font-size:14px;"></span><pre name="code" class="java">import com.spider.java.JavaSpider_1_5; import com.spider.service.JavaSpider_1_5_Service; import com.spider.service.impl.JavaSpider_1_5_ServiceImpl; /** * * @author Administrator * * 在JavaSpider 1.3 的基础上,对爬取的网址,进行分类存储 * * 1,把temp_url 临时网址,存储到临时表 temp_url 中; * 2,把target_url 目标网址,存储到目标表 target_url 中; * */ @SuppressWarnings("serial") public class SaveToDifferentDatabase_JavaSpider_1_5_Servlet extends HttpServlet{ //定义service层接口对象 JavaSpider_1_5_Service javaSpider_1_5_Service = new JavaSpider_1_5_ServiceImpl(); //service层接口对象 的 setter方法 public void setJavaSpider_1_5_Service(JavaSpider_1_5_Service javaSpider_1_5_Service) { //测试输出 System.out.println("JavaSpider_1_5 版本 JavaSpider_1_5_Service 接口对象 的 setter 方法执行了... "); this.javaSpider_1_5_Service = javaSpider_1_5_Service; } //实现doPost方法 public void doPost(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ //设置相应信息的编码方式 response.setCharacterEncoding("UTF-8"); //定义一个String类型的变量,用来表示用户输入的URL String URL = ""; //定义一个String类型的变量,用来表示用户输入的URL int LEVEL = 0; //定义一个String类型的变量,用来表示返回客户端的提示信息 String message = ""; //生成Temp_url对象 Temp_url url_temp = new Temp_url(); //生成Target_url对象 Target_url target_url = new Target_url(); //定义一个Map,用来封装所有的URL网址 Map<Integer,String> urls = new HashMap<Integer,String>(); // Map<Integer,String> urls_rs = new HashMap<Integer,String>(); //生成JavaSpider_1_3_URLParser对象 JavaSpider_1_5 javaSpider_1_5 = new JavaSpider_1_5(); //生成日期对象 Date current_date = new Date(); //设置日期格式化样式为:yyyy-MM-dd SimpleDateFormat SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd"); //格式化当前日期 SimpleDateFormat.format(current_date.getTime()); //在request请求域中获取参数 LEVEL = Integer.parseInt(request.getParameter("LEVEL")); URL = request.getParameter("URL"); //测试输出 System.out.println("在servlet中接收到的用户输入的网址:" + URL); if(!"".equals(URL)){ //测试输出 System.out.println(" 在servlet中 ,!''.equals(URL):如果URL不为空,进入if语句..."); //获取所有的URL网址 urls = javaSpider_1_5.getFormatCode_1_5(URL); //封装url实体 for(int i=0;i<urls.size();i++){ /* * 对网址进行分类存储,如果是临时网址,则保存到临时表;如果是目标网址,则保存到目标表 */ //如果是目标网址 if(urls.get(i).toLowerCase().endsWith(".html")){ target_url.setTempurl(urls.get(i)); target_url.setLevel(LEVEL); //调用业务逻辑处理对象,完成数据保存到数据库的业务逻辑 javaSpider_1_5_Service.saveToDatabaseTarget_url(target_url); //测试输出 System.out.println("目标网址保存到目标数据库 target_url "); } //如果是临时网址 else{ url_temp.setTempurl(urls.get(i)); url_temp.setLevel(LEVEL); //调用业务逻辑处理对象,完成数据保存到数据库的业务逻辑 javaSpider_1_5_Service.saveToDatabase(url_temp); //测试输出 System.out.println("临时网址保存到临时数据库 url_temp "); } } message = "文件保存完成..."; //把信息保存到request请求域中,传递到客户端 request.setAttribute("message", message); //跳转到SpiderIndex.jsp页面 request.getRequestDispatcher("WEB-INF/spider/Success.jsp").forward(request, response); } else{ urls_rs = javaSpider_1_5_Service.getAllUrlsOfLevel(LEVEL); //封装url实体 for(int i=0;i<urls_rs.size();i++){ urls = javaSpider_1_5.getFormatCode_1_5(urls_rs.get(i)); //测试输出 System.out.println("查询结果集中的网址 urls_rs.get(i) = " + urls_rs.get(i)); System.out.println("新爬取的网址 urls.get(i) = " + urls.get(i)); for(int j=0;j<urls.size();j++){ /* * 对网址进行分类存储,如果是临时网址,则保存到临时表;如果是目标网址,则保存到目标表 */ //如果是目标网址 if(urls.get(i).toLowerCase().endsWith(".html")){ target_url.setTempurl(urls.get(i)); target_url.setLevel(LEVEL); //调用业务逻辑处理对象,完成数据保存到数据库的业务逻辑 javaSpider_1_5_Service.saveToDatabaseTarget_url(target_url); } //如果是临时网址 else{ url_temp.setTempurl(urls.get(i)); url_temp.setLevel(LEVEL); //调用业务逻辑处理对象,完成数据保存到数据库的业务逻辑 javaSpider_1_5_Service.saveToDatabase(url_temp); } } } message = "文件保存完成..."; //把信息保存到request请求域中,传递到客户端 request.setAttribute("message", message); //跳转到SpiderIndex.jsp页面 request.getRequestDispatcher("WEB-INF/spider/Success.jsp").forward(request, response); } } //实现doGet方法 public void doGet(HttpServletRequest request,HttpServletResponse response) throws ServletException,IOException{ //设置相应信息的编码方式 response.setCharacterEncoding("UTF-8"); this.doPost(request, response); } }
package com.spider.java; import java.io.IOException; import java.util.Map; import org.apache.http.client.ClientProtocolException; public interface JavaSpiderBase_1_5 { //带参数的方法 JavaSpider_1_5版本 public Map<Integer,String> getFormatCode_1_5(String URL) throws ClientProtocolException, IOException; }
package com.spider.java; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.util.HashMap; import java.util.Map; import org.apache.http.HttpEntity; import org.apache.http.HttpResponse; import org.apache.http.HttpStatus; import org.apache.http.client.ClientProtocolException; import org.apache.http.client.HttpClient; import org.apache.http.client.methods.HttpGet; import org.apache.http.impl.client.DefaultHttpClient; @SuppressWarnings("deprecation") public class JavaSpider_1_5 implements JavaSpiderBase_1_5{ @Override public Map<Integer, String> getFormatCode_1_5(String URL) throws ClientProtocolException, IOException { //创建HttpClient HttpClient httpClient = new DefaultHttpClient(); //获取HttpGet对象 HttpGet httpGet = new HttpGet(URL); // @SuppressWarnings("unused") StringBuffer stringBuffer = new StringBuffer(); // HttpResponse httpResoponse = httpClient.execute(httpGet); // BufferedReader bufferedReader; //定义一个Map,用来封装所有的URL Map<Integer,String> urls = new HashMap<Integer,String>(); //生成JavaSpider_1_4_URLParser对象 JavaSpider_1_4_URLParser javaSpider_1_4_URLParser = new JavaSpider_1_4_URLParser(); if(HttpStatus.SC_OK == httpResoponse.getStatusLine().getStatusCode()){ // HttpEntity httpEntity = httpResoponse.getEntity(); // if(httpEntity != null){ bufferedReader = new BufferedReader(new InputStreamReader(httpEntity.getContent(),"UTF-8")); //bufferedReader按行读取 String line = ""; //if(httpEntity.getContentLength() > 0 ){ if(httpEntity.getContent() != null && httpEntity.getContentLength() > 0){ stringBuffer = new StringBuffer((int) httpEntity.getContentLength()); int z = 0; while((line = bufferedReader.readLine()) != null){ //判断得到的目标网址是否为空 if(!"".equals(javaSpider_1_4_URLParser.parserURL(line, URL))){ //封装到数组中 urls.put(z, javaSpider_1_4_URLParser.parserURL(line, URL)); System.out.println("if在JavaSpider中测试输出获取到的所有网址:" + urls.get(z)); z++; } } } //如果httpEntity.getContent() != null && httpEntity.getContentLength() == -1 else{ //测试输出 System.out.println("进入if...进入条件:httpEntity.getContent() != null || httpEntity.getContentLength() == -1"); //stringBuffer = new StringBuffer((int) httpEntity.getContentLength()); //把长度写死 stringBuffer = new StringBuffer(1024); int z = 0; while((line = bufferedReader.readLine()) != null){ //判断得到的目标网址是否为空 if(!"".equals(javaSpider_1_4_URLParser.parserURL(line, URL))){ //封装到数组中 urls.put(z, javaSpider_1_4_URLParser.parserURL(line, URL)); System.out.println("else在JavaSpider中测试输出获取到的所有网址:" + urls.get(z)); z++; } } } } if(httpEntity != null){ // httpEntity.consumeContent(); } } //返回Map return urls; } }
package com.spider.java; public class JavaSpider_1_5_HTMLParser { // public String parserHTML(String line){ //定义一个String类型的变量parseredLine,用来表示处理以后的line String parseredLine = ""; //第一次抽取后的子串 String subString = ""; //第二次抽取后的子串 String sub_subString = ""; //第三次抽取后的子串 String sub_sub_subString = ""; int i = line.indexOf('<'); int j = line.lastIndexOf('<'); int k = line.indexOf('>'); //1,如果字符<第一次出现的索引和最后一次出现的索引值相等,说明这一行,只有一对<></> 这种闭合的HTML标签; //此时只需要把这个标签删除掉就行,我们可以使用String类的subString方法截取我们需要的信息; if(i == j && i != -1){ //这种情况下, 我们还要再判断,这个标签是不是位于行首; if(i == 0 ){ //System.out.println(""); //简化处理 } else{ //System.out.println(""); //简化处理,暂时不考虑<br>这种单独的标签 } } //如果字符< 第一次出现的索引和最后一次出现的索引值不相同,说明这一行,有2对<></>或者多对, 这样的闭合的HTML标签; //2,如果有2对闭合的HTML标签;此时我们需要删除这2对HTML标签;这里简化步骤,只考虑闭合标签位于首尾的情况; else if(i != j){ //第一次抽取 subString = line.substring(k+1, j); //第二次抽取 //第二次抽取的时候,需要考虑2个标签的特殊情况,也就是title、link这种标签,虽然符合条件,但是不抽取这种值。 int y = subString.lastIndexOf('<'); int z = subString.indexOf('>'); if(y > -1){ //此时还要考虑只有3个HTML标签的特殊情况 if(subString.contains("<title") || subString.contains("<link" )){ sub_subString = subString.substring(z+1, y); } else{ sub_subString = subString.substring(z+1, y); if(sub_subString != null && (sub_subString.startsWith("0") || sub_subString.startsWith("1") || sub_subString.startsWith("2") || sub_subString.startsWith("3") || sub_subString.startsWith("4") || sub_subString.startsWith("5") || sub_subString.startsWith("6") || sub_subString.startsWith("7") || sub_subString.startsWith("8") || sub_subString.startsWith("9"))){ } else{ System.out.println(sub_subString); parseredLine = sub_subString; } } } //第三次抽取 int A = sub_subString.indexOf('<'); int B = sub_subString.indexOf('>'); int C = sub_subString.lastIndexOf('<'); //如果A<0,说明没有HTML标签了; if(A < 0){ //System.out.println(""); } //如果A>0,说明还有HTML标签,此时需要判断是只有一个,还是有多个; else{ //如果A = C,说明,只有一个HTML标签,此时还有三种情况,HTML标签在首,HTML标签居中,HTML标签在尾; if(A == C && A == 0){ sub_sub_subString = sub_subString.substring(B+1, sub_subString.length()); System.out.println(sub_sub_subString); parseredLine = sub_sub_subString; } else if(A == C && (B == sub_subString.length() - 1)){ sub_sub_subString = sub_subString.substring(0, A); System.out.println(sub_sub_subString); parseredLine = sub_sub_subString; } else if(A == C && A != 0 && (B != sub_subString.length() - 1 )){ //如果HTML标签居中,我们这时需要根据java的语法来判断, //此时还需要判断,我们需要抽取的内容在哪边,这时我们根据HTML标签内,有没有/来判断 //如果书写规范的话,没有/,则我们需要抽取的内容在后边;否则在前边; //这种情况下,还要进行第四次抽取的判断; //如果开头是数字,可以判断我们需要抽取的代码在尾部 if(sub_subString.substring(0, 1).matches("^[0-9]")){ sub_sub_subString = sub_subString.substring(B+1,sub_subString.length()); System.out.println(sub_sub_subString); parseredLine = sub_sub_subString; } else{ sub_sub_subString = sub_subString.substring(0, A); System.out.println(sub_sub_subString); parseredLine = sub_sub_subString; } } } } return parseredLine; } }
package com.spider.java; public class JavaSpider_1_5_URLParser { /** * 实现方法: * * 1,直接获取第一个A标签的起始位置,然后截取想要的属性,或者A标签; * 2,然后从剩下的二级子串中,重复进行第一步的操作; * 3,以此类推,我们就可以获取所有的A标签了... * * 此方法需要接收以下几个参数: * 1,当前页面的网址current_url,String类型; * 2,当前需要处理的行line,String类型; */ public String parserURL(String line,String current_url){ //目标网址前缀 target_url_prefix String target_url_prefix = ""; //目标网址 String target_url = ""; //目标网址后缀 String target_url_suffix = ""; /* * 第一次抽取 */ //定义一个int变量,用来表示第一个 A 标签起始位置的索引 int a_start = -100; //定义一个int变量,用来表示第一个 A 标签的 href 属性起始位置的索引 int href_start = -100; //定义一个int变量,用来表示第一个 A 标签的 第一个双引号 起始位置的索引 int double_start = -100; //定义一个String类型的变量,用来表示截取的子串,我们称之为一级子串 String sub_String = ""; //定义一个String类型的变量,用来表示截取的子串的子串,我们称之为二级子串 String sub_sub_String = ""; /* * 首先对当前网址current_url进行处理,获得目标网址前缀 */ int current_url_index = current_url.lastIndexOf("/"); target_url_prefix = current_url.substring(0, current_url_index+1); //测试输出 //System.out.println("当前输入的URL ==== " + current_url); //System.out.println("目标网址前缀 target_url_prefix ==== " + target_url_prefix); //获取第一个A标签的索引 if(line.contains("<a")){ a_start = line.indexOf("<a"); sub_String = line.substring(a_start); //测试输出 System.out.println("一级子串 sub_String = " + sub_String); href_start = sub_String.indexOf("href="); sub_sub_String = sub_String.substring(href_start+6); //测试输出 System.out.println("二级子串 sub_sub_String = " + sub_sub_String); //如果二级子串非法,也就是href的第一位不是字母 if(sub_sub_String.startsWith("?") || sub_sub_String.startsWith("/")){ //测试输出 System.out.println("非法网址,不保存!"); } else{ double_start = sub_sub_String.indexOf("\""); target_url_suffix = sub_sub_String.substring(0, double_start); //测试输出 System.out.println("目标网址后缀 target_url_suffix = " + target_url_suffix); } } //如果目标网址后缀 target_url_suffix 不为空 if(!"".equals(target_url_suffix)){ //目标网址为 target_url = target_url_prefix + target_url_suffix; //测试输出 //System.out.println("当前获得的目标网址为 target_url:" + target_url); } //返回目标网址 return target_url; } }
其他代码,可以在我的资源里面下载 :http://download.csdn.net/detail/reggergdsg/9406609
稍后继续更新爬虫1.6