`
wb17534806
  • 浏览: 11073 次
  • 性别: Icon_minigender_1
  • 来自: 长沙
社区版块
存档分类
最新评论

一个简单的蜘蛛程序

阅读更多

一个简单的蜘蛛程序,没有实现多线程,只考虑了一些特定的情况。

一句话:一切从简!

下载提供测试页面。

源码:

package com.wans.spider;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.sun.java_cup.internal.internal_error;
import com.sun.org.apache.bcel.internal.generic.NEW;

public class MySpider1 implements Runnable {


 static ArrayList<String> waitUrlList = new ArrayList<String>();            //等待处理的urls
 static ArrayList<String> disposeUrlList = new ArrayList<String>();     //要处理的urls
 static ArrayList<String> errorUrlList = new ArrayList<String>();           //处理出错的urls
 static ArrayList<String> overUrlList = new ArrayList<String>();            //处理完成的urls
 //static ArrayList<String> outUrlList = new ArrayList<String>();             //发现外链urls
 
 static ArrayList<String> Allhost=new ArrayList<String>();                  //存放主机
 
 static String webUrl = "http://192.168.0.25:8080/test_net_for_spider/";
 //static String webUrl = "http://127.0.0.1:8080/test_net_for_spider/";       //对某个网站进行爬取
 static long outtime = 1000;                                                //连接超时时间
 static int ceng = 5;                                                       //查询的层数
 static int timeout = 10000;                                                //连接超时
 static int sheng = 4;                                                      //爬取深度
 static int threads = 1;                                                    //抓取线程数为1
 
 
 public static void main(String[] args) {
  MySpider1 spider1 = new MySpider1();
  for (int i = 1; i <= threads; i++) {
   Thread thread = new Thread(spider1);
   thread.start();
  }
 }

 //使用多线程提高效率
 public void run() {
  //调用主体方法
  body();
 }
 
 //主体方法
 private static void body() {
  //输出爬取开始基本信息
  info();  
  //将爬取网站加入等待处理的urls
  waitUrlList.add(webUrl);
  System.out.println("webUrl:"+webUrl+" 已添加到 "+waitUrlList);
  //检查等待处理的urls是否为空,不为空,将urls传到disposeUrlList。为空,停止爬取。
  //处理urls,发现链接,判断是否是外链。是,加入outUrlList。不是,加入等待队列。
  for(int i=1;i<=sheng;i++) {
   if(waitUrlList.isEmpty() || waitUrlList.size() == 0) {
    System.out.println("\r爬取结束。。。。");
    overinfo();//统计爬取结束信息
    break;
   } else {
    disposeUrlList.addAll(waitUrlList);//将等待urls加入处理urls
    System.out.println("waitUrlList 加入 disposeUrlList 中 进行处理");
    waitUrlList.clear(); //清空urls,为下次使用做准备。
    for (String url : disposeUrlList) {
     //获取url中的超链接,保证无重复。
     ArrayList<String> urlsList = getUrls(url);
     for (String urlt : urlsList) {
      if(!disposeUrlList.contains(urlt) && !overUrlList.contains(urlt)) {
       waitUrlList.add(urlt);
      }
     }
    }
    overUrlList.addAll(disposeUrlList);  //完成urls
    System.out.println("处理连接结束,写入 overUrlList");
    System.out.println("处理过连接的个数:   "+overUrlList.size());    
    disposeUrlList.clear();   
   }
  }
 }
 
 
 //获取网页里的超链接,加入等待urls
 private static ArrayList<String> getUrls(String url) {
  ArrayList<String> urlsArrayList = new ArrayList<String>();   //存放链接
  //获得网页内容
  String urlConent = getHtml(url);
  if(urlConent != null) {
   //分析文本内容,获取链接
   String regex="<a href.*</a>"; 
   String output=null;                                 //第一次提取的<a href  *  </a>
   String outputUrl=null;                            //对第一次提取的Url再次过滤
   Pattern pa=Pattern.compile(regex, Pattern.DOTALL);
   Matcher ma=pa.matcher(urlConent);                            //初次过滤  
   while(ma.find()){
    output=ma.group().trim();
    regex="<a\\s+href\\s*=\\s*\"?(.*?)[\"|>]";             //再次过滤
    // regex="http\\s*\"?(.*?)[\"|>]";
    Pattern paa=Pattern.compile(regex,Pattern.DOTALL);
    Matcher maa=paa.matcher(output);
    while(maa.find()){
     outputUrl=maa.group().trim();
     // System.out.println();
     // System.out.println(outputUrl);
     if (outputUrl.length() < 1) {
      continue;
     }
     //********************************************
     //根据实际情况 过渡网页的某些垃圾信息
     outputUrl=outputUrl.replace("<a href=", "");
     outputUrl=outputUrl.replace("\"", "");
     outputUrl=outputUrl.replace(">", "");
     outputUrl=outputUrl.replace("/>", "");
     outputUrl=outputUrl.replace("class=","");
     outputUrl=outputUrl.replace("target=_blank", "");
     outputUrl=outputUrl.replace("'target=_blank'", "");
     outputUrl=outputUrl.replace("'_blank'", "");
     outputUrl=outputUrl.replace("target=_self", "");
     outputUrl=outputUrl.replace("target=", "");
     outputUrl=outputUrl.replace("style=", "");
     outputUrl=outputUrl.replace("../", "");
     outputUrl=outputUrl.replace("#", "");
     outputUrl=outputUrl.replace("title=", "");
     outputUrl=outputUrl.replace("<a  href=", "");
     outputUrl=outputUrl.replace("'", "");
     //*********************
//     int endUrl=outputUrl.indexOf(" ");            //处理url有空格问题
//     if(endUrl>0){                              //要是有空格才截断
//      outputUrl=outputUrl.substring(0,endUrl);  //以空格为结束
//     }
     //*************************
     outputUrl=outputUrl.trim();    //过滤空间
     if(outputUrl.length()>0){
      if(outputUrl.indexOf("://")==-1){    //处理相对地址
       int length=webUrl.length();
       int find=webUrl.lastIndexOf("/")+1;
       if(length==find){
        outputUrl=webUrl+outputUrl;           //  如果以/结尾
       }else{
        outputUrl=webUrl+"/"+outputUrl;     //  如果不以 /结尾
       }
      }
      int begin2=outputUrl.lastIndexOf("//")+2;  //检查是否是以 //结尾
      if(begin2==outputUrl.length()){
       outputUrl=outputUrl.substring(0, outputUrl.length()-1); //  把   //变成/
      }
      if(!urlsArrayList.contains(outputUrl)){               //去掉重复的url
       urlsArrayList.add(outputUrl);
      }
     }
    }
   }
  }
  return urlsArrayList;
 }
 
 //获取网页内容
 private static String getHtml(String url) {
  StringBuffer urlConent = new StringBuffer(); //装url中内容  
  try {
   URL urlpath = new URL(url);    //对应连接地址
   String urlHost = urlpath.getHost(); //获取地址主机
   if("".equals(urlHost) && !Allhost.contains(urlHost)) {     //将主机加入
    Allhost.add(urlHost);
   }
   HttpURLConnection urlcon = (HttpURLConnection)urlpath.openConnection();
   HttpURLConnection.setFollowRedirects(true); //设置此类是否应该自动执行 HTTP 重定向(响应代码为 3xx 的请求)。
   urlcon.setInstanceFollowRedirects(false);     //返回此 HttpURLConnection 的 instanceFollowRedirects 字段的值。
   urlcon.setConnectTimeout(timeout);            //设置超时,这里直接调用系统设置的
   //将读超时设置为指定的超时,以毫秒为单位。用一个非零值指定在建立到资源的连接后从 Input 流读入时的超时时间。
   //如果在数据可读取之前超时期满,则会引发一个 java.net.SocketTimeoutException。超时时间为零表示无穷大超时。
   //此方法的一些非标准实现会忽略指定的超时。要查看读入超时设置,请调用 getReadTimeout()。
   urlcon.setReadTimeout(timeout); 
   urlcon.connect();  //打开到此 URL 引用的资源的通信链接(如果尚未建立这样的连接)。
   System.out.println("\r正在连接 ...");
   System.out.println("地址是: "+url);
   String contentType=urlcon.getContentType();
   System.out.println("方式为: "+contentType+"    状态: "+urlcon.getResponseMessage());
   System.out.println("正在读取HTML流 ......");
   
   String s="";
   BufferedReader br = new BufferedReader(new InputStreamReader(urlcon.getInputStream()));
   while((s=br.readLine()) != null) {
    urlConent.append(s);
   }
   double size = urlConent.length();
   System.out.println("ok   读取了 "+size/1024+"KB");
  } catch (MalformedURLException e) {   
   e.printStackTrace();
  } catch (IOException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }  
  return urlConent.toString();  
 }
 
 //爬取结束信息
 private static void overinfo() {
  String info = null;
  info += "本次爬取网页总数为:"+overUrlList.size()+"\r";
  info += "错误网页总数为:"+errorUrlList.size()+"\r";
  info += "爬取结束时间:" + getTime();
  System.out.println(info);
 }
 
 //输出爬取开始基本信息
 private static void info() {
  String info = null;
  info += "爬取开始时间:" + getTime() + "\r";
  info += "主机地址:" + webUrl + "\r";
  info += "超时时间是:" + outtime  + "\r";
  info += "查询的层数:" + ceng + "\r";
  info += "限定主机搜索!" + "\r\r";
  info += "启动爬取程序。。。。。\r";
  System.out.println(info);
 }
 
 //获取时间
 private static String getTime() {
  SimpleDateFormat format = new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss");
  return format.format(new Date());
 } 
 
}
 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics