首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

從零構建搜索引擎(一):Java 實現網絡爬蟲核心模塊

     編輯:Java 相關知識

系列規劃

  1. 爬蟲模塊 (本文):網頁收集、URL 去重、多線程抓取、原始頁面庫存儲。
  2. 預處理模塊:HTML 清洗、中文分詞、正排/倒排索引建立。
  3. 查詢服務模塊:分詞查詢、相關度排序 (PageRank)、快照生成、前端展示。

整體架構與數據流

搜索引擎三段式工作流程

搜索引擎整體結構

核心流程

  1. 用戶查詢 -> 分詞去停用詞 -> 倒排索引匹配候選文檔集。
  2. 候選集 -> 相關度計算 (BM25/PageRank) -> 排序輸出。
  3. 索引來源:爬蟲抓取原始頁 -> HTML 分析提取正文 -> 分詞 -> 正排索引 (Doc->Terms) -> 倒排索引 (Term->Docs)。

爬蟲 設計

抓取策略:廣度優先 (BFS)

Web 可視為有向圖 (節點=網頁,邊=超鏈接)。BFS 更利於發現高質量頁面、控制抓取深度、均衡站點負載。

工作流程

Spider 工作流程

  1. Dispatcher 維護 <待訪問隊列> 與 <已訪問集合> (單例模式,線程安全)。
  2. Gather 線程從 Dispatcher 取 URL -> HTTP GET -> 讀取響應流 -> 存入頁面庫 -> 解析頁面提取 URL -> 送回 Dispatcher。
  3. Dispatcher 去重 (已訪問集合) 後入隊。

核心模塊實現

1. 網頁收集器 Gather

URL url = new URL("https://www.example.com");
URLConnection conn = url.openConnection();
BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
StringBuilder doc = new StringBuilder();
String line;
while ((line = reader.readLine()) != null) doc.append(line).append("\n");
// doc.toString() 即原始 HTML

優勢:Java URLConnection 封裝底層 Socket/HTTP 協議,開發者聚焦業務邏輯。

2. 頁面存儲格式 (參考北大天網簡化版)


[記錄 1]
Version: 1
Date: 2024-01-15
IP: 192.168.1.1
Content-Length: 12345

<html>...原始 HTML 內容...</html>

[記錄 2]
...
  • 順序寫入,便於批量掃描處理。
  • 記錄頭含元數據 (版本、日期、IP、長度),支援增量更新判斷 (日期變更 -> 重新抓取)。

3. URL 識別與提取 (正則表達式)


String patternStr = "<[aA]\\s+href=([^>]*\\s*>)";
Pattern pattern = Pattern.compile(patternStr, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(htmlDoc);
List urls = new ArrayList<>();
while (matcher.find()) {
    String tag = matcher.group(); // 完整  標簽
    int firstQuote = tag.indexOf('"');
    int secondQuote = tag.indexOf('"', firstQuote + 1);
    if (secondQuote > firstQuote) {
        String url = tag.substring(firstQuote + 1, secondQuote);
        urls.add(url);
    }
}

4. URL 整理與過濾

  • 相對路徑轉絕對:基於當前頁面 URL 拼接 (new URL(baseUrl, relativeUrl))。
  • 去除廣告/垃圾鏈接:URL 含 ad, track, click 等關鍵字降低優先級或直接丟棄。
  • 協議過濾:僅保留 http/https,忽略 javascript:, mailto:, ftp:。

5. Dispatcher 分配器 (單例 + 線程安全)


public class Dispatcher {
    private static Dispatcher instance = new Dispatcher();
    private Queue unvisited = new LinkedBlockingQueue<>();
    private Set visited = ConcurrentHashMap.newKeySet();
    
    private Dispatcher() {}
    public static Dispatcher getInstance() { return instance; }
    
    public synchronized String getNextUrl() { return unvisited.poll(); }
    public synchronized void addVisited(String url) { visited.add(url); }
    public synchronized boolean isVisited(String url) { return visited.contains(url); }
    public synchronized void addUnvisited(String url) { if (!isVisited(url)) unvisited.offer(url); }
}

6. 多線程啟動


public class Spider {
    private int gatherNum = 10; // 線程數
    public void start() {
        Dispatcher disp = Dispatcher.getInstance();
        for (int i = 0; i < gatherNum; i++) {
            new Thread(new Gather(disp)).start();
        }
    }
}

Gather.run() 中循環 disp.getNextUrl() -> 抓取 -> 解析 -> disp.addUnvisited(),synchronized 保證隊列操作原子性。

小結與擴展方向

  • 爬蟲是搜索引擎地基,穩定性、去重效率、禮貌策略 (robots.txt、抓取間隔) 決定上層數據質量。
  • 輕量修改即可轉型為垂直爬蟲 (圖片站、新聞站、電商價格監控)。
  • 生產級建議:引入 HttpClient 連接池、BloomFilter 億級去重、Kafka 解耦抓取與解析、分散式調度 (Scrapy-Redis / Apache Nutch)。
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved