java实现的简单网页爬虫:Servlet + MySQL5.5


/*

 *  * JavaSpier的目标:
 *
 * 1,我们要获取的是
 * http://commons.apache.org/proper/commons-fileupload/apidocs/src-html/org/apache/commons/
 * Apache org.apache.commons站点下的所有源代码文件,也就是最终的.html文件。
 *,2,我们要对获取到的源代码网页,进行格式化处理,以java源代码的方式,保存到指定文件中。
 * 3,每个.html页面保存到对应的.java文件中。这些文件都保存到电脑的指定目录下。
 *
 * JavaSpier 1.3版本 我们实现了以下功能:
 * 1,自动检索当前网址所在网页的HTML内容,并从中抽取所有的URL地址,然后保存到数据库中;
 * 2,需要说明的是,这里保存的网址,有的是.html结尾的,有的是一个目录,比如.../fileupload/
 * 3,在JavaSpier 1.3版本,我们并没有将网页内容保存到文件中,因为我们的目的是先获得所有的目标网址,然后统一处理;
 *
 */

该系统,我们使用的servlet + MySQL5.5来实现的。

系统关键文件结构如下:

前台JSP页面:
/Spider/WebRoot/WEB-INF/spider/GetAllUrl_JavaSpider_1_3.jsp  
/Spider/WebRoot/WEB-INF/spider/Error.jsp
/Spider/WebRoot/WEB-INF/spider/Success.jsp

后台java文件:
/Spider/src/com/spider/dao/JavaSpider_1_3_Dao.java                              Dao层接口
/Spider/src/com/spider/dao/impl/JavaSpider_1_3_DaoImpl.java             Dao层实现类

/Spider/src/com/spider/service/JavaSpider_1_3_Service.java                  Service层接口
/Spider/src/com/spider/service/impl/JavaSpider_1_3_ServiceImpl.java Service层实现类

/Spider/src/com/spider/servlet/GetAllUrl_JavaSpider_1_3_Servlet.java  Servlet控制类

/Spider/src/com/spider/java/JavaSpiderBase_1_3.java                              爬虫核心接口
/Spider/src/com/spider/java/JavaSpider_1_3.java                                        爬虫核心接口实现类
/Spider/src/com/spider/java/JavaSpider_1_3_URLParser.java                 对网页中的链接进行处理的工具类,以行为单位,获取网页中的所有URL地址
/Spider/src/com/spider/java/JavaSpider_1_3_HTMLParser.java              对网页进行抽取的工具类,也就是去掉HTML标签,得到网页内容

配置文件:

/Spider/WebRoot/WEB-INF/web.xml


下面贴上所有文件的源代码,可能较多,大家耐心...

/Spider/WebRoot/WEB-INF/spider/GetAllUrl_JavaSpider_1_3.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    <title>JavaSpider 抓取所有的目标网址,保存到数据库</title>
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
</head>
  
<body>
<div>
    <form class="STYLE-NAME" action="GetAllUrl_JavaSpider_1_3_Servlet" method="post">
    <label>
    <span>  JavaSpier 1.3版本</span>
    </label><br>
    <label>
    <span>  我们进行了以下改进:</span>
    </label><br>
    <label>
    <span>  1,从指定网页,抓取该网页中的所有的网址,保存到数据库</span>
    </label><br>
    <label>
    <span>  2,需要说明的是,这里保存的网址,有的是.html结尾的,有的是一个目录,比如.../fileupload/</span>
    </label><br>
    <label>
    <span>  3,比如下面这个网址,我们可以获取该网址下,所有的二级网址,并保存到数据库中...</span>
    </label><br>
    <label>
    <span>  http://commons.apache.org/proper/commons-fileupload/apidocs/src-html/org/apache/commons/fileupload/</span>
    </label><br>
    <label>
    <span>后缀级别level:</span>
    <input type="text" name="LEVEL">
    </label><br>
    <label>
    <span>请输入网址:</span>
    <input type="text" name="URL" id="">
    </label><br>
    <input type="submit" name="submit" id="" value="点击保存到数据库中">
    </form>
</div>
</body>
</html>

/Spider/WebRoot/WEB-INF/spider/Error.jsp
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>程序出现异常</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
	<meta http-equiv="description" content="This is my page">
  </head>
<div>
    <form class="STYLE-NAME" action="">
    <label>
    <span>  程序出现异常</span>
    </label><br>
    <label>
    <span>  </span>
    </label><br>
    </form>
</div>
</html>

/Spider/WebRoot/WEB-INF/spider/Success.jsp

<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>文件保存成功</title>
    <meta http-equiv="pragma" content="no-cache">
    <meta http-equiv="cache-control" content="no-cache">
    <meta http-equiv="expires" content="0">    
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="This is my page">
  </head>
<div>
    <form class="STYLE-NAME" action="">
    <label>
    <span>  如果文件保存成功,则跳转到这个页面</span>
    </label><br>
    <label>
    <span>  </span>
    </label><br>
    </form>
</div>
<!-- 显示服务器端传递过来的提示信息message -->
<div>
<c:if test=""></c:if>
<c:out value="${request.message}"></c:out>
<label><span> A ${message}</span></label>

</div>
</html>

后台java文件:
/Spider/src/com/spider/dao/JavaSpider_1_3_Dao.java                      Dao层接口

package com.spider.dao;

import java.util.Map;
import com.spider.Model.Temp_url;
import com.spider.Model.Url;

public interface JavaSpider_1_3_Dao {
	//增
	public boolean saveToDatabase(Url url);
	//增
	public boolean saveToDatabase(Temp_url temp_url);
	//查
	public Map<Integer,String> getAllUrlsOfLevel(int level);
}

/Spider/src/com/spider/dao/impl/JavaSpider_1_3_DaoImpl.java             Dao层实现类

ackage com.spider.dao.impl;

import java.sql.ResultSet;
import java.util.HashMap;
import java.util.Map;
import com.spider.Model.Temp_url;
import com.spider.Model.Url;
import com.spider.dao.JavaSpider_1_3_Dao;
import com.spider.util.JavaSpider_JDBC;

public class JavaSpider_1_3_DaoImpl implements JavaSpider_1_3_Dao {

    @Override
    public boolean saveToDatabase(Temp_url temp_url) {
        //创建数据库连接对象
        JavaSpider_JDBC JavaSpider_JDBC = new JavaSpider_JDBC();
        //定义一个Boolean类型的变量,用来表示数据库操作是否成功
        boolean flag = false;

        //用PreparedStatement
        String sql = "insert into temp_url(id,url,level) values(null,?,?)";

        try{

            //调用dao层增加方法,把数据插入到数据库
            JavaSpider_JDBC.javaSpider_JDBC(sql);
            //执行数据库操作,如何执行预处理的SQL语句,请参考PreparedStatement源码,如下
            JavaSpider_JDBC.pst.setString(1, temp_url.getTempurl());
            JavaSpider_JDBC.pst.setInt(2, temp_url.getLevel());
            JavaSpider_JDBC.pst.execute();
            //测试输出
            System.out.println("数据库插入成功...");
            flag = true;
        }
        catch(Exception e){
            //测试输出
            System.out.println("数据库插入异常...");
            e.printStackTrace();
        }
        return flag;
    }

    @Override
    public boolean saveToDatabase(Url url) {
        //创建数据库连接对象
        JavaSpider_JDBC JavaSpider_JDBC = new JavaSpider_JDBC();
        //定义一个Boolean类型的变量,用来表示数据库操作是否成功
        boolean flag = false;

        //用PreparedStatement
        String sql = "insert into url(id,url,date) values(null,?,?)";
        
        try{

            //调用dao层增加方法,把数据插入到数据库
            JavaSpider_JDBC.javaSpider_JDBC(sql);
            //执行数据库操作,如何执行预处理的SQL语句,请参考PreparedStatement源码,如下
            JavaSpider_JDBC.pst.setString(1, url.getUrl());
            JavaSpider_JDBC.pst.setString(2, url.getDate());
            JavaSpider_JDBC.pst.execute();
            //测试输出
            System.out.println("数据库插入成功...");
            flag = true;
        }
        catch(Exception e){
            //测试输出
            System.out.println("数据库插入异常...");
            e.printStackTrace();
        }
        return flag;
    }

    @Override
    public Map<Integer, String> getAllUrlsOfLevel(int level) {
        //创建数据库连接对象
        JavaSpider_JDBC JavaSpider_JDBC = new JavaSpider_JDBC();
        //查询结果集
        ResultSet resultSet;
        //Map<Integer, String>
        Map<Integer, String> urls = new HashMap<Integer, String>();

        //用PreparedStatement
        String sql = "select url from temp_url where level=?";
        
        try{

            //调用dao层增加方法,把数据插入到数据库
            JavaSpider_JDBC.javaSpider_JDBC(sql);
            //执行数据库操作,如何执行预处理的SQL语句,请参考PreparedStatement源码,如下
            JavaSpider_JDBC.pst.setInt(1, level);
            resultSet = JavaSpider_JDBC.pst.executeQuery();
            //把查询结果保存到Map中
            int i = 1;
            while(resultSet.next()){
                urls.put(i-1, resultSet.getString("url"));
                System.out.println("dao测试:" + urls.get(i-1));
                i++;
            }
            
            //测试输出
            System.out.println("数据库插入成功...");
        }
        catch(Exception e){
            //测试输出
            System.out.println("数据库插入异常...");
            e.printStackTrace();
        }
        return urls;
    }
    
}


/Spider/src/com/spider/service/JavaSpider_1_3_Service.java              Service层接口

package com.spider.service;

import java.util.Map;

import com.spider.Model.Temp_url;
import com.spider.Model.Url;

public interface JavaSpider_1_3_Service {
	//增
	public boolean saveToDatabase(Url url);
	//增
	public boolean saveToDatabase(Temp_url temp_url);
	//查
	public Map<Integer,String> getAllUrlsOfLevel(int level);
}

/Spider/src/com/spider/service/impl/JavaSpider_1_3_ServiceImpl.java     Service层实现类

package com.spider.service.impl;

import java.util.HashMap;
import java.util.Map;
import com.spider.Model.Temp_url;
import com.spider.Model.Url;
import com.spider.dao.JavaSpider_1_3_Dao;
import com.spider.dao.impl.JavaSpider_1_3_DaoImpl;
import com.spider.service.JavaSpider_1_3_Service;

public class JavaSpider_1_3_ServiceImpl implements JavaSpider_1_3_Service {
	
	//定义Dao层接口对象
	JavaSpider_1_3_Dao javaSpider_1_3_Dao = new JavaSpider_1_3_DaoImpl(); 

	public JavaSpider_1_3_Dao getJavaSpider_1_3_Dao() {
		return javaSpider_1_3_Dao;
	}

	public void setJavaSpider_1_3_Dao(JavaSpider_1_3_Dao javaSpider_1_3_Dao) {
		this.javaSpider_1_3_Dao = javaSpider_1_3_Dao;
	}

	@Override
	public boolean saveToDatabase(Temp_url temp_url) {
		//定义一个Boolean类型的变量,用来表示数据库操作是否成功
		boolean flag = false;
		//
		flag = javaSpider_1_3_Dao.saveToDatabase(temp_url);

		return flag;
	}

	@Override
	public boolean saveToDatabase(Url url) {
		//定义一个Boolean类型的变量,用来表示数据库操作是否成功
		boolean flag = false;
		//
		flag = javaSpider_1_3_Dao.saveToDatabase(url);

		return flag;
	}

	@Override
	public Map<Integer, String> getAllUrlsOfLevel(int level) {
		
		Map<Integer, String> urls = new HashMap<Integer, String>();
		
		urls = javaSpider_1_3_Dao.getAllUrlsOfLevel(level);
		
		return urls;
	}
}

/Spider/src/com/spider/servlet/GetAllUrl_JavaSpider_1_3_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.Temp_url;
import com.spider.java.JavaSpider_1_3;
import com.spider.service.JavaSpider_1_3_Service;
import com.spider.service.impl.JavaSpider_1_3_ServiceImpl;

@SuppressWarnings("serial")
public class GetAllUrl_JavaSpider_1_3_Servlet extends HttpServlet{
    
	//定义service层接口对象
	JavaSpider_1_3_Service javaSpider_1_3_Service = new JavaSpider_1_3_ServiceImpl();
	
	//setter、getter方法
	public JavaSpider_1_3_Service getJavaSpider_1_3_Service() {
		return javaSpider_1_3_Service;
	}
	public void setJavaSpider_1_3_Service(JavaSpider_1_3_Service javaSpider_1_3_Service) {
		this.javaSpider_1_3_Service = javaSpider_1_3_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 = "";
		//生成url对象
		Temp_url url_temp = new Temp_url();
		//定义一个Map,用来封装所有的URL网址
		Map<Integer,String> urls = new HashMap<Integer,String>();
		//
		Map<Integer,String> urls_rs = new HashMap<Integer,String>();
		//定义一个Map,用来封装所有的url对象
		Map<Integer,Temp_url> url_entity = new HashMap<Integer,Temp_url>();
		//生成JavaSpider_1_3_URLParser对象
		JavaSpider_1_3 javaSpider_1_3 = new JavaSpider_1_3();
	        //生成日期对象
	        Date current_date = new Date();
	        //设置日期格式化样式为:yyyy-MM-dd
	        SimpleDateFormat  SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd");
	        //格式化当前日期
	        SimpleDateFormat.format(current_date.getTime());
		//url.setUrl(URL);
		//url.setDate(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_3.getFormatCode_1_3(URL);
		    
		    //封装url实体
		    for(int i=0;i<urls.size();i++){
		    	url_temp.setTempurl(urls.get(i));
		    	url_temp.setLevel(LEVEL);
		    	url_entity.put(i, url_temp);
		    	//调用业务逻辑处理对象,完成数据保存到数据库的业务逻辑
		    	javaSpider_1_3_Service.saveToDatabase(url_entity.get(i));
		    }
				
			//调用业务逻辑处理对象,完成数据保存到数据库的业务逻辑
			//for(int j=0;j<url_entity.size();j++){
				//javaSpider_1_3_Service.saveToDatabase(url_entity.get(j));
			//}
				
			message = "文件保存完成...";
				
			//把信息保存到request请求域中,传递到客户端
			request.setAttribute("message", message);
				
			//跳转到SpiderIndex.jsp页面
			request.getRequestDispatcher("WEB-INF/spider/Success.jsp").forward(request, response);

		}
		
		else{
			urls_rs = javaSpider_1_3_Service.getAllUrlsOfLevel(LEVEL);
			
			
			
		    //封装url实体
		    for(int i=0;i<urls_rs.size();i++){
		    	//url_temp.setTempurl(urls_rs.get(i));
		    	//url_temp.setLevel(LEVEL);
		    	//url_entity.put(i, url_temp);
		    	
		    	urls = javaSpider_1_3.getFormatCode_1_3(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++){
		    		url_temp.setTempurl(urls.get(j));
		    		url_temp.setLevel(LEVEL);
		    		url_entity.put(j, url_temp);
			    	//测试输出
			    	System.out.println("新抓取的网址 = " + urls.get(j));
		    		javaSpider_1_3_Service.saveToDatabase(url_entity.get(j));
		    	}
		    }
				
				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");	
	}
	
}

/Spider/src/com/spider/java/JavaSpiderBase_1_3.java                     爬虫核心接口

package com.spider.java;

import java.io.IOException;
import java.util.Map;
import org.apache.http.client.ClientProtocolException;

public interface JavaSpiderBase_1_3 {

    //带参数的方法 JavaSpider_1_3版本
    public Map<Integer,String> getFormatCode_1_3(String URL) throws ClientProtocolException, IOException;
}

/Spider/src/com/spider/java/JavaSpider_1_3.java                         爬虫核心接口实现类

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;

/*
 * JavaSpier 1.3版本 之 网页内容处理类public class JavaSpider_1_3
 * 我们进行了以下改进:
 * 1,增加自动搜索目标网页的功能,先实现把一个站点下的网址都保存起来的功能。
 * 2,把一个站点下的网址,都保存到数据库中;
 * 
 * 在网页内容处理类public class JavaSpider_1_3,我们主要进行网页的爬取和文件IO的业务逻辑;
 * 网页抽取的操作从这个类中剥离;
 */
@SuppressWarnings("deprecation")
public class JavaSpider_1_3 implements JavaSpiderBase_1_3{
	
	//定义一个String变量,用来表示新生成的文件的存放路径
	public static final String FILE_PATH = "E:\\uploadFiles\\";

	@Override
	public Map<Integer,String> getFormatCode_1_3(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_3_URLParser对象
		JavaSpider_1_3_URLParser javaSpider_1_3_URLParser = new JavaSpider_1_3_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_3_URLParser.parserURL_2(line, URL))){
							
							//封装到数组中
							
							urls.put(z, javaSpider_1_3_URLParser.parserURL_2(line, URL));
							
							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_3_URLParser.parserURL_2(line, URL))){
							
							//封装到数组中
							
							urls.put(z, javaSpider_1_3_URLParser.parserURL_2(line, URL));
							
							//System.out.println("在JavaSpider中测试输出获取到的所有网址:" + urls.get(z));
							
							z++;
						}
					
					}
				}
			}
			if(httpEntity != null){
				//
				httpEntity.consumeContent();
			}
		}
		
		//返回Map
		return urls;
	}
}

/Spider/src/com/spider/java/JavaSpider_1_3_URLParser.java               对网页中的链接进行处理的工具类,以行为单位,获取网页中的所有URL地址

package com.spider.java;

/*
 *  * JavaSpier的目标:
 * 
 * 1,我们要获取的是http://commons.apache.org/proper/commons-fileupload/apidocs/src-html/org/apache/commons/
 * Apache org.apache.commons站点下的所有源代码文件,也就是最终的.html文件。
 *,2,我们要对获取到的源代码网页,进行格式化处理,以java源代码的方式,保存到指定文件中。
 * 3,每个.html页面保存到对应的.java文件中。这些文件都保存到电脑的指定目录下。
 * 
 * JavaSpier 1.3版本 之 网页内容处理类public class JavaSpider_1_3_URLParser
 * 我们进行了以下改进:
 * 1,自动检索当前网址所在网页的HTML内容,并从中抽取所有的URL地址,然后保存到数据库中;
 * 2,需要说明的是,这里保存的网址,有的是.html结尾的,有的是一个目录,比如.../fileupload/
 * 3,在JavaSpier 1.3版本,我们并没有将网页内容保存到文件中,因为我们的目的是先获得所有的目标网址,然后统一处理;
 * 
 * 在网页A标签处理类public class JavaSpider_1_3_URLParser,
 * 我们对网页中的链接进行处理,返回目标网址;
 */
public class JavaSpider_1_3_URLParser {

	/**
	 * 第二种实现方法:
	 * 
     * 1,直接获取第一个A标签的起始位置,然后截取想要的属性,或者A标签; 
     * 2,然后从剩下的二级子串中,重复进行第一步的操作;
     * 3,以此类推,我们就可以获取所有的A标签了...
     * 
	 * 此方法需要接收以下几个参数:
	 * 1,当前页面的网址current_url,String类型;
	 * 2,当前需要处理的行line,String类型;
	 */
	public String parserURL_2(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;
	}
}

/Spider/src/com/spider/java/JavaSpider_1_3_HTMLParser.java              对网页进行抽取的工具类,也就是去掉HTML标签,得到网页内容

package com.spider.java;

public class JavaSpider_1_3_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('>');
		//int m = line.lastIndexOf('>');
		//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;
	}
}

/Spider/src/com/spider/Model/Temp_url.java                              实体类
package com.spider.Model;

public class Temp_url {
	/*
	 * 数据库名称:test
	 * 
	 * 表名称:temp_url
	 * 字段1,id,主键,auto_increment;
	 * 字段2,url,varchar(200) not null
	 * 字段3,level,int(4),not null
	 * 
	 * 建表语句:
       create table temp_url(
       id int auto_increment primary key,
       url varchar(200) not null,
       level int(4) not null
       );
       
     * 测试数据
     * insert into url(id,url,date) values(null,"http://commons.apache.org/proper/commons-fileupload/apidocs/src-

html/org/apache/commons/fileupload/portlet/PortletFileUpload.html#line.51",now());
     * 
     * url字段长度50不够用,我们把长度修改为100
     * alter table url modify url varchar(200) not null;
     */

	//id,主键,自增长
	int id;
	//临时URL,不是有效的URL
	String tempurl;
	//时间,date
	int level;
	
	//setter、getter方法
	public int getId() {
		return id;
	}
	public void setId(int id) {
		this.id = id;
	}
	public String getTempurl() {
		return tempurl;
	}
	public void setTempurl(String tempurl) {
		this.tempurl = tempurl;
	}
	public int getLevel() {
		return level;
	}
	public void setLevel(int level) {
		this.level = level;
	}
	
}

配置文件:web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app version="3.0" 
	xmlns="http://java.sun.com/xml/ns/javaee" 
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xsi:schemaLocation="http://java.sun.com/xml/ns/javaee 
	http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd">
  <display-name>JavaSpider</display-name>	

<!-- 配置servlet 用于设置Servlet的注册名称和Servlet的完整类名-->

<!-- 抓取所有的目标网址,保存到数据库 -->
<servlet>
    <servlet-name>GetAllUrl_JavaSpider_1_3_Servlet</servlet-name>
    <servlet-class>com.spider.servlet.GetAllUrl_JavaSpider_1_3_Servlet</servlet-class>
</servlet>

<!-- 配置servlet-mapping 用于映射一个已注册的Servlet的一个对外访问路径-->
<!-- 注意:-->
<!--     1,url-pattern是对外访问路径,对应JSP页面的action的值-->
<!--     2,客户端发送的action请求,对应url-pattern斜杠后面的参数;-->
<!--     3,action请求找到url-pattern以后,根据servlet-name去找对应的servlet类;-->
<!--     4,servlet类接收到客户端的请求以后,开始处理请求;-->

<!-- 抓取所有的目标网址,保存到数据库 -->
<servlet-mapping>
    <servlet-name>GetAllUrl_JavaSpider_1_3_Servlet</servlet-name>
    <url-pattern>/GetAllUrl_JavaSpider_1_3_Servlet</url-pattern>
</servlet-mapping>

</web-app>

这是一个没有经过优化的,简单的爬虫,可以爬取指定站点的网页,并将链接保存到数据库中。后续还会更新更高版本...



你可能感兴趣的:(mysql,servlet,网络爬虫,javaweb开发)