`

一个Java Web搜索程序

    博客分类:
  • JAVA
阅读更多
这是一个web搜索的基本程序,从命令行输入搜索条件(起始的URL、处理url的最大数、要搜索的字符串),
它就会逐个对Internet上的URL进行实时搜索,查找并输出匹配搜索条件的页面。 这个程序的原型来自《java编程艺术》,
为了更好的分析,站长去掉了其中的GUI部分,并稍作修改以适用jdk1.5。以这个程序为基础,可以写出在互联网上搜索
诸如图像、邮件、网页下载之类的“爬虫”。
先请看程序运行的过程: 


D:\java>javac  SearchCrawler.java(编译) 

D:\java>java   SearchCrawler http://127.0.0.1:8080/zz3zcwbwebhome/index.jsp 20 java 

Start searching... 
result: 
searchString=java 
http://127.0.0.1:8080/zz3zcwbwebhome/index.jsp 
http://127.0.0.1:8080/zz3zcwbwebhome/reply.jsp 
http://127.0.0.1:8080/zz3zcwbwebhome/learn.jsp 
http://127.0.0.1:8080/zz3zcwbwebhome/download.jsp 
http://127.0.0.1:8080/zz3zcwbwebhome/article.jsp 
http://127.0.0.1:8080/zz3zcwbwebhome/myexample/jlGUIOverview.htm 
http://127.0.0.1:8080/zz3zcwbwebhome/myexample/Proxooldoc/index.html 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=301 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=297 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=291 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=286 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=285 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=284 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=276 
http://127.0.0.1:8080/zz3zcwbwebhome/view.jsp?id=272   

又如: 
D:\java>java    SearchCrawler http://www.sina.com  20 java 
Start searching... 
result: 
searchString=java 
http://sina.com 
http://redirect.sina.com/WWW/sinaCN/www.sina.com.cn class=a2 
http://redirect.sina.com/WWW/sinaCN/www.sina.com.cn class=a8 
http://redirect.sina.com/WWW/sinaHK/www.sina.com.hk class=a2 
http://redirect.sina.com/WWW/sinaTW/www.sina.com.tw class=a8 
http://redirect.sina.com/WWW/sinaUS/home.sina.com class=a8 
http://redirect.sina.com/WWW/smsCN/sms.sina.com.cn/ class=a2 
http://redirect.sina.com/WWW/smsCN/sms.sina.com.cn/ class=a3 
http://redirect.sina.com/WWW/sinaNet/www.sina.net/ class=a3 


D:\java> 
下面是这个程序的源码 

import java.util.*;
import java.net.*;
import java.io.*;
import java.util.regex.*;
// 搜索Web爬行者
public class SearchCrawler implements Runnable{
 
/* disallowListCache缓存robot不允许搜索的URL。 Robot协议在Web站点的根目录下设置一个robots.txt文件,
  *规定站点上的哪些页面是限制搜索的。 搜索程序应该在搜索过程中跳过这些区域,下面是robots.txt的一个例子:
 # robots.txt for http://somehost.com/
   User-agent: *
   Disallow: /cgi-bin/
   Disallow: /registration # /Disallow robots on registration page
   Disallow: /login
  */
  private HashMap< String,ArrayList< String>> disallowListCache = new HashMap< String,ArrayList< String>>(); 
  ArrayList< String> errorList= new ArrayList< String>();//错误信息 
  ArrayList< String> result=new ArrayList< String>(); //搜索到的结果 
  String startUrl;//开始搜索的起点
  int maxUrl;//最大处理的url数
  String searchString;//要搜索的字符串(英文)
  boolean caseSensitive=false;//是否区分大小写
  boolean limitHost=false;//是否在限制的主机内搜索
  
  public SearchCrawler(String startUrl,int maxUrl,String searchString){
   this.startUrl=startUrl;
   this.maxUrl=maxUrl;
   this.searchString=searchString;
  }
   public ArrayList< String> getResult(){
       return result;
   }
  public void run(){//启动搜索线程
      
       crawl(startUrl,maxUrl, searchString,limitHost,caseSensitive);
  }
   
    //检测URL格式
  private URL verifyUrl(String url) {
    // 只处理HTTP URLs.
    if (!url.toLowerCase().startsWith("http://"))
      return null;
    URL verifiedUrl = null;
    try {
      verifiedUrl = new URL(url);
    } catch (Exception e) {
      return null;
    }
    return verifiedUrl;
  }
  // 检测robot是否允许访问给出的URL.
 private boolean isRobotAllowed(URL urlToCheck) { 
    String host = urlToCheck.getHost().toLowerCase();//获取给出RUL的主机 
    //System.out.println("主机="+host);
    // 获取主机不允许搜索的URL缓存 
    ArrayList< String> disallowList =disallowListCache.get(host); 
    // 如果还没有缓存,下载并缓存。 
    if (disallowList == null) { 
      disallowList = new ArrayList< String>(); 
      try { 
        URL robotsFileUrl =new URL("http://" + host + "/robots.txt"); 
        BufferedReader reader =new BufferedReader(new InputStreamReader(robotsFileUrl.openStream())); 
        // 读robot文件,创建不允许访问的路径列表。 
        String line; 
        while ((line = reader.readLine()) != null) { 
          if (line.indexOf("Disallow:") == 0) {//是否包含"Disallow:" 
            String disallowPath =line.substring("Disallow:".length());//获取不允许访问路径 
            // 检查是否有注释。 
            int commentIndex = disallowPath.indexOf("#"); 
            if (commentIndex != - 1) { 
              disallowPath =disallowPath.substring(0, commentIndex);//去掉注释 
            } 
             
            disallowPath = disallowPath.trim(); 
            disallowList.add(disallowPath); 
           } 
         } 
        // 缓存此主机不允许访问的路径。 
        disallowListCache.put(host, disallowList); 
      } catch (Exception e) { 
              return true; //web站点根目录下没有robots.txt文件,返回真
      } 
    } 
     
    String file = urlToCheck.getFile(); 
    //System.out.println("文件getFile()="+file);
    for (int i = 0; i < disallowList.size(); i++) { 
      String disallow = disallowList.get(i); 
      if (file.startsWith(disallow)) { 
        return false; 
      } 
    } 
    return true; 
  } 
 
  private String downloadPage(URL pageUrl) {
     try {
        // Open connection to URL for reading.
        BufferedReader reader =
          new BufferedReader(new InputStreamReader(pageUrl.openStream()));
        // Read page into buffer.
        String line;
        StringBuffer pageBuffer = new StringBuffer();
        while ((line = reader.readLine()) != null) {
          pageBuffer.append(line);
        }
        
        return pageBuffer.toString();
     } catch (Exception e) {
     }
     return null;
  }
  // 从URL中去掉"www"
  private String removeWwwFromUrl(String url) {
    int index = url.indexOf("://www.");
    if (index != -1) {
      return url.substring(0, index + 3) +
        url.substring(index + 7);
    }
    return (url);
  }
  // 解析页面并找出链接
  private ArrayList< String> retrieveLinks(URL pageUrl, String pageContents, HashSet crawledList,
    boolean limitHost)
  {
    // 用正则表达式编译链接的匹配模式。
    Pattern p =Pattern.compile("< a\\s+href\\s*=\\s*\"?(.*?)[\"|>]",Pattern.CASE_INSENSITIVE);
    Matcher m = p.matcher(pageContents);
    
    ArrayList< String> linkList = new ArrayList< String>();
    while (m.find()) {
      String link = m.group(1).trim();
      
      if (link.length() < 1) {
        continue;
      }
      // 跳过链到本页面内链接。
      if (link.charAt(0) == '#') {
        continue;
      }
      
      if (link.indexOf("mailto:") != -1) {
        continue;
      }
     
      if (link.toLowerCase().indexOf("javascript") != -1) {
        continue;
      }
      if (link.indexOf("://") == -1){
        if (link.charAt(0) == '/') {//处理绝对地  
          link = "http://" + pageUrl.getHost()+":"+pageUrl.getPort()+ link;
        } else {         
          String file = pageUrl.getFile();
          if (file.indexOf('/') == -1) {//处理相对地址
            link = "http://" + pageUrl.getHost()+":"+pageUrl.getPort() + "/" + link;
          } else {
            String path =file.substring(0, file.lastIndexOf('/') + 1);
            link = "http://" + pageUrl.getHost() +":"+pageUrl.getPort()+ path + link;
          }
        }
      }
      int index = link.indexOf('#');
      if (index != -1) {
        link = link.substring(0, index);
      }
      link = removeWwwFromUrl(link);
      URL verifiedLink = verifyUrl(link);
      if (verifiedLink == null) {
        continue;
      }
      /* 如果限定主机,排除那些不合条件的URL*/
      if (limitHost &&
          !pageUrl.getHost().toLowerCase().equals(
            verifiedLink.getHost().toLowerCase()))
      {
        continue;
      }
      // 跳过那些已经处理的链接.
      if (crawledList.contains(link)) {
        continue;
      }
       linkList.add(link);
    }
   return (linkList);
  }
 // 搜索下载Web页面的内容,判断在该页面内有没有指定的搜索字符串
  private boolean searchStringMatches(String pageContents, String searchString, boolean caseSensitive){
       String searchContents = pageContents; 
       if (!caseSensitive) {//如果不区分大小写
          searchContents = pageContents.toLowerCase();
       }
    
    Pattern p = Pattern.compile("[\\s]+");
    String[] terms = p.split(searchString);
    for (int i = 0; i < terms.length; i++) {
      if (caseSensitive) {
        if (searchContents.indexOf(terms[i]) == -1) {
          return false;
        }
      } else {
        if (searchContents.indexOf(terms[i].toLowerCase()) == -1) {
          return false;
        }
      }     }
    return true;
  }
  
  //执行实际的搜索操作
  public ArrayList< String> crawl(String startUrl, int maxUrls, String searchString,boolean limithost,boolean caseSensitive )
  { 
    
    System.out.println("searchString="+searchString);
    HashSet< String> crawledList = new HashSet< String>();
    LinkedHashSet< String> toCrawlList = new LinkedHashSet< String>();
     if (maxUrls < 1) {
        errorList.add("Invalid Max URLs value.");
        System.out.println("Invalid Max URLs value.");
      }
  
    
    if (searchString.length() < 1) {
      errorList.add("Missing Search String.");
      System.out.println("Missing search String");
    }
    
    if (errorList.size() > 0) {
      System.out.println("err!!!");
      return errorList;
      }
    
    // 从开始URL中移出www
    startUrl = removeWwwFromUrl(startUrl);
    
    toCrawlList.add(startUrl);
    while (toCrawlList.size() > 0) {
      
      if (maxUrls != -1) {
        if (crawledList.size() == maxUrls) {
          break;
        }
      }
      // Get URL at bottom of the list.
      String url =  toCrawlList.iterator().next();
      // Remove URL from the to crawl list.
      toCrawlList.remove(url);
      // Convert string url to URL object.
      URL verifiedUrl = verifyUrl(url);
      // Skip URL if robots are not allowed to access it.
      if (!isRobotAllowed(verifiedUrl)) {
        continue;
      }
    
      // 增加已处理的URL到crawledList
      crawledList.add(url);
      String pageContents = downloadPage(verifiedUrl);
      
      if (pageContents != null && pageContents.length() > 0){
        // 从页面中获取有效的链接
        ArrayList< String> links =retrieveLinks(verifiedUrl, pageContents, crawledList,limitHost);
     
        toCrawlList.addAll(links);
        if (searchStringMatches(pageContents, searchString,caseSensitive))
        {
          result.add(url);
          System.out.println(url);
        }
     }
    
    }
   return result;
  }
  // 主函数
  public static void main(String[] args) {
     if(args.length!=3){
        System.out.println("Usage:java SearchCrawler startUrl maxUrl searchString");
        return;
     }
    int max=Integer.parseInt(args[1]);
    SearchCrawler crawler = new SearchCrawler(args[0],max,args[2]);
    Thread  search=new Thread(crawler);
    System.out.println("Start searching...");
    System.out.println("result:");
    search.start();
   
  }
}

 

分享到:
评论

相关推荐

    Web服务器的java实现

    目标:采用Socket和多线程技术,实现一个java Web服务器,加深对HTTP的认识。 新建java项目 webServer 新建java文件 WebServer.java Processor.java  一、HTTP协议的作用原理  WWW是以Internet作为...

    WebViewGold for Android v13.8网站和Web应用程序转换为Android应用程序项目源码JAVA

    一个很好的方法来获得数百万的Google Play商店客户。无需编码,无需更多插件。它只是工作。 完整的Android应用程序模板-无需编码!#nocode 24/7人工实时聊天支持和AI可搜索文档 适用于在Chrome浏览器上运行的任何Web...

    Java源码包100个设计实例.zip

    java 一个消息发布网站.rar Java 数字签名、数字证书生成源码.rar Java 版的酒店系统,貌似完整.rar Java 电梯模拟程序 v2.0.rar Java 组播组中发送和接受数据实例 Java 飞机订票.rar Java 高考信息管理系统 SQL...

    java源码包---java 源码 大量 实例

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    Java毕业设计-[其他类别]UrlRewriter Java v2.0 RC1_urlrewriterjava.rar

    总之,UrlRewriter Java v2.0 RC1是一个功能强大、易于使用的URL重写过滤器,可以帮助开发人员优化Java Web应用程序的URL结构,提高用户体验和搜索引擎优化效果。对于需要实现URL友好化和优化的Java Web应用程序项目...

    Java Web典型模块与项目实战大全

    每个项目都从软件工程的角度出发,从开发背景、需求分析、系统功能分析、数据库分析、数据库结构、系统开发到系统的编译发行,每一过程都进行了详细的讲解。 环境搭建篇包括JDK的下载与安装、Eclipse的下载与使用、...

    JAVA上百实例源码以及开源项目

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    java搜索引擎源码

    网络中的资源非常丰富,但是如何有效的搜索信息却是一件困难的事情。建立搜索引擎就是解决这个...本文首先详细介绍了基于英特网的搜索引擎的系统结构,然后从网络机器人、索引引擎、Web服务器三个方面进行详细的说明

    JAVA上百实例源码以及开源项目源代码

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 3...

    爬虫搜索,简单的搜索引擎,java爬虫,搜索引擎例子,爬虫demo,java实现互联网内容抓取,搜索引擎大揭密

    爬虫搜索,简单的搜索引擎,java爬虫,搜索引擎例子,爬虫demo,java实现互联网内容抓取,搜索引擎大揭密.java爬虫程序。web搜索。爬虫程序。sigar搜索,定时搜索互联网内容信息。

    My-Java-Forum:这是一个全栈Java Web应用程序

    这是一个全栈Java Web应用程序。 与所有论坛一样,您可以在Java论坛中搜索,回复或发布主题。 并且,如果您以管理员身份登录,则还可以修改或删除该帖子。 我使用JSP,HTML和JavaScript在前端显示Web,并使用Java,...

    java源码包4

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 ...

    java源码包3

     Tcp服务端与客户端的JAVA实例源代码,一个简单的Java TCP服务器端程序,别外还有一个客户端的程序,两者互相配合可以开发出超多的网络程序,这是最基础的部分。 递归遍历矩阵 1个目标文件,简单! 多人聊天室 ...

    Java微信小程序商城

    系统WEB合并 platform-gen 代码生成 platform-schedule 定时任务 platform-shiro 登陆权限相关 platform-shop 商城后台管理 wx-mall 微信小程序商城 实现功能 一:会员管理 会员管理 ...

    java web项目实验,包括一个医院挂号系统和微信小程序实验.zip

    零安装:用户只需通过微信扫一扫或搜索功能,即可打开和使用小程序,大大降低了用户的使用门槛和手机存储空间压力。 速度快:加载速度相较于传统的HTML5网页更快,依托于微信强大的基础设施,能够实现近乎原生应用...

    Java写的爬虫的基本程序

    这是一个web搜索的基本程序,从命令行输入搜索条件(起始的URL、处理url的最大数、要搜索的字符串), 它就会逐个对Internet上的URL进行实时搜索,查找并输出匹配搜索条件的页面。 这个程序的原型来自《java编程艺术》...

    java开源包11

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包6

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    java开源包9

    WebSocket4J 是一个用 Java 实现的 WebSocket 协议的类库,可使用 Java 来构建交互式 Web 应用。WebSocket4J 并未实现客户端通讯协议,所以不能用它来连接 WebSocket 服务器。 Struts验证码插件 JCaptcha4Struts2 ...

    图书查询-Java-Web程序设计教程-[共2页].pdf

    Java Web 程序设计教程 300 页 &lt;/div&gt; &lt;/div&gt; &lt;/div&gt; &lt;jsp:include page="foot.jsp"&gt;&lt;/jsp:include&gt; &lt;/body&gt; &lt;/html&gt; 14.5 图书查询 在 head.jsp 页面中,不只有登录、注销和注册功能,在它们的下面,还有图书查询...

Global site tag (gtag.js) - Google Analytics