<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    走在架構(gòu)師的大道上 Jack.Wang's home

    Java, C++, linux c, C#.net 技術(shù),軟件架構(gòu),領(lǐng)域建模,IT 項(xiàng)目管理 Dict.CN 在線詞典, 英語(yǔ)學(xué)習(xí), 在線翻譯

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      195 Posts :: 3 Stories :: 728 Comments :: 0 Trackbacks
            超簡(jiǎn)單的 Web 爬蟲(chóng)程序,不過(guò)可以在他基礎(chǔ)之上改造一下,寫(xiě)出強(qiáng)大點(diǎn)的爬蟲(chóng)!
            謝謝提供程序的 blog 友!
           

    /**
     * @author Jack.Wang
     *
     */
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.net.URL;
    import java.util.ArrayList;
    import java.util.HashMap;
    import java.util.HashSet;
    import java.util.LinkedHashSet;
    import java.util.regex.Matcher;
    import java.util.regex.Pattern;

    // 搜索Web爬行者
    public class SearchCrawler implements Runnable {

     /*
      * disallowListCache緩存robot不允許搜索的URL。 Robot協(xié)議在Web站點(diǎn)的根目錄下設(shè)置一個(gè)robots.txt文件,
      * 規(guī)定站點(diǎn)上的哪些頁(yè)面是限制搜索的。
      * 搜索程序應(yīng)該在搜索過(guò)程中跳過(guò)這些區(qū)域,下面是robots.txt的一個(gè)例子:
      * # 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>();// 錯(cuò)誤信息
     ArrayList<String> result = new ArrayList<String>(); // 搜索到的結(jié)果
     String startUrl;// 開(kāi)始搜索的起點(diǎn)
     int maxUrl;// 最大處理的url數(shù)
     String searchString;// 要搜索的字符串(英文)
     boolean caseSensitive = false;// 是否區(qū)分大小寫(xiě)
     boolean limitHost = false;// 是否在限制的主機(jī)內(nèi)搜索

     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() {// 啟動(dòng)搜索線程
      crawl(startUrl, maxUrl, searchString, limitHost, caseSensitive);
     }

     // 檢測(cè)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;
     }

     // 檢測(cè)robot是否允許訪問(wèn)給出的URL.
     private boolean isRobotAllowed(URL urlToCheck) {
      String host = urlToCheck.getHost().toLowerCase();// 獲取給出RUL的主機(jī)
      // System.out.println("主機(jī)="+host);

      // 獲取主機(jī)不允許搜索的URL緩存
      ArrayList<String> disallowList = disallowListCache.get(host);

      // 如果還沒(méi)有緩存,下載并緩存。
      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文件,創(chuàng)建不允許訪問(wèn)的路徑列表。
        String line;
        while ((line = reader.readLine()) != null) {
         if (line.indexOf("Disallow:") == 0) {// 是否包含"Disallow:"
          String disallowPath = line.substring("Disallow:"
            .length());// 獲取不允許訪問(wèn)路徑

          // 檢查是否有注釋。
          int commentIndex = disallowPath.indexOf("#");
          if (commentIndex != -1) {
           disallowPath = disallowPath.substring(0,
             commentIndex);// 去掉注釋
          }

          disallowPath = disallowPath.trim();
          disallowList.add(disallowPath);
         }
        }

        // 緩存此主機(jī)不允許訪問(wèn)的路徑。
        disallowListCache.put(host, disallowList);
       } catch (Exception e) {
        return true; // web站點(diǎn)根目錄下沒(méi)有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);
     }

     // 解析頁(yè)面并找出鏈接
     private ArrayList<String> retrieveLinks(URL pageUrl, String pageContents,
       HashSet crawledList, boolean limitHost) {
      // 用正則表達(dá)式編譯鏈接的匹配模式。
      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;
       }

       // 跳過(guò)鏈到本頁(yè)面內(nèi)鏈接。
       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) == '/') {// 處理絕對(duì)地
         link = "http://" + pageUrl.getHost() + ":"
           + pageUrl.getPort() + link;
        } else {
         String file = pageUrl.getFile();
         if (file.indexOf('/') == -1) {// 處理相對(duì)地址
          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;
       }

       /* 如果限定主機(jī),排除那些不合條件的URL */
       if (limitHost
         && !pageUrl.getHost().toLowerCase().equals(
           verifiedLink.getHost().toLowerCase())) {
        continue;
       }

       // 跳過(guò)那些已經(jīng)處理的鏈接.
       if (crawledList.contains(link)) {
        continue;
       }

       linkList.add(link);
      }

      return (linkList);
     }

     // 搜索下載Web頁(yè)面的內(nèi)容,判斷在該頁(yè)面內(nèi)有沒(méi)有指定的搜索字符串

     private boolean searchStringMatches(String pageContents,
       String searchString, boolean caseSensitive) {
      String searchContents = pageContents;
      if (!caseSensitive) {// 如果不區(qū)分大小寫(xiě)
       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;
     }

     // 執(zhí)行實(shí)際的搜索操作
     public ArrayList<String> crawl(String startUrl, int maxUrls,
       String searchString, boolean limithost, boolean caseSensitive) {

      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;
      }

      // 從開(kāi)始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) {
        // 從頁(yè)面中獲取有效的鏈接
        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;
     }

     // 主函數(shù)
     public static void main(String[] args) {
      SearchCrawler crawler = new SearchCrawler("http://www.tkk7.com/Jack2007/", 20,"jack");
      Thread search = new Thread(crawler);
      System.out.println("Start searching...");
      System.out.println("result:");
      search.start();
      try {
       search.join();
      } catch (InterruptedException e) {
       // TODO Auto-generated catch block
       e.printStackTrace();
      }
     }
    }





    本博客為學(xué)習(xí)交流用,凡未注明引用的均為本人作品,轉(zhuǎn)載請(qǐng)注明出處,如有版權(quán)問(wèn)題請(qǐng)及時(shí)通知。由于博客時(shí)間倉(cāng)促,錯(cuò)誤之處敬請(qǐng)諒解,有任何意見(jiàn)可給我留言,愿共同學(xué)習(xí)進(jìn)步。
    posted on 2008-03-24 09:32 Jack.Wang 閱讀(23440) 評(píng)論(4)  編輯  收藏 所屬分類(lèi): 開(kāi)發(fā)技術(shù)

    Feedback

    # re: 超簡(jiǎn)單的 Web 爬蟲(chóng)程序(轉(zhuǎn)貼) 2008-08-01 15:45 豚豚
    呵呵,正要看這方面的東西呢~
    謝謝啦~  回復(fù)  更多評(píng)論
      

    # re: 超簡(jiǎn)單的 Web 爬蟲(chóng)程序(轉(zhuǎn)貼) 2009-11-11 20:30 張牧宇
    有個(gè)問(wèn)題,樓主把爬下來(lái)的網(wǎng)頁(yè)存到硬盤(pán)了嗎,怎么存?  回復(fù)  更多評(píng)論
      

    # re: 超簡(jiǎn)單的 Web 爬蟲(chóng)程序(轉(zhuǎn)貼) 2009-11-11 20:31 張牧宇
    有個(gè)問(wèn)題,樓主把爬下來(lái)的網(wǎng)頁(yè)存到硬盤(pán)了嗎,怎么存?

    qq 125474591 加好友聊吧  回復(fù)  更多評(píng)論
      

    # re: 超簡(jiǎn)單的 Web 爬蟲(chóng)程序(轉(zhuǎn)貼) 2016-05-26 19:34 abby
    我覺(jué)得對(duì)于開(kāi)發(fā)者來(lái)說(shuō),能腳本化編寫(xiě)爬蟲(chóng)是一件挺開(kāi)心的事情( ̄▽?zhuān)?"。所以我們團(tuán)隊(duì)開(kāi)發(fā)了一個(gè)專(zhuān)門(mén)讓開(kāi)發(fā)者用簡(jiǎn)單的幾行 javascript 就能在云上編寫(xiě)和運(yùn)行復(fù)雜爬蟲(chóng)的系統(tǒng),叫神箭手云爬蟲(chóng)開(kāi)發(fā)平臺(tái): http://www.shenjianshou.cn 。歡迎同行們來(lái)試用拍磚,盡情給俺們提意見(jiàn)。有想法的可以加群討論: 342953471  回復(fù)  更多評(píng)論
      

    主站蜘蛛池模板: 国产亚洲人成网站在线观看不卡| 久久不见久久见免费影院| 四虎影视免费永久在线观看| 亚洲娇小性xxxx| 青草草色A免费观看在线| 亚洲一区无码中文字幕乱码| 91成人免费在线视频| 亚洲人成黄网在线观看| 成人片黄网站A毛片免费| 亚洲中文字幕久久无码| 久久亚洲精品成人AV| 91福利免费视频| 自拍日韩亚洲一区在线| 成年性生交大片免费看| 亚洲一卡一卡二新区无人区| 国产美女被遭强高潮免费网站| 日韩亚洲人成网站| 亚洲女人被黑人巨大进入| 在线观看片免费人成视频无码| 亚洲av永久无码精品漫画| 久久WWW免费人成一看片| 亚洲一区二区三区国产精品无码| 啦啦啦在线免费视频| japanese色国产在线看免费| 亚洲精品人成在线观看| 成熟女人牲交片免费观看视频| 美女羞羞免费视频网站| 亚洲成a人片在线观看日本| www.免费在线观看| 亚洲a∨国产av综合av下载| 亚洲精品tv久久久久| 欧洲人成在线免费| 国产精品亚洲片在线va| 亚洲麻豆精品国偷自产在线91| 亚洲成人免费在线| 亚洲AV成人精品一区二区三区 | 亚洲视频在线免费看| 亚洲经典千人经典日产| 2021久久精品免费观看| 曰批免费视频播放免费| 67pao强力打造67194在线午夜亚洲 |