2025年3月21日 星期五

設計一個高流量的爬蟲 API 即服務的詳細需求

文件:Laravel 10 爬蟲 API 服務設計

1. 引言

本文件旨在詳細說明 Laravel 10 爬蟲 API 服務的設計,包括 API 規範、資料建模和系統架構。本服務旨在提供一個可擴展、高效能的平台,用於爬取網站內容並儲存結構化數據。

2. API 規範 (環境部屬)

  • 身份驗證:
    • 使用 tymon/jwt-auth 套件進行 JWT 身份驗證,確保 API 端點的安全性。
    • 使用 Laravel Gates 或 Policies 實現授權機制,控制使用者存取權限。
  • API 特性:
    • RESTful 設計,使用 HTTP 方法 (POST, GET) 和資源。
    • GET 端點具備冪等性,多次調用產生相同結果。
  • 端點:
    • POST /auth/login:使用者登入,取得 JWT。
    • POST /crawl/single:爬取單個頁面 (需要 JWT 驗證)。
    • POST /crawl/website:爬取整個網站 (需要 JWT 驗證)。
    • GET /crawl/{id}:檢索爬取結果 (需要 JWT 驗證)。
    • POST /crawl/{id}/suspend:暫停爬取任務 (需要 JWT 驗證)。
  • 輸入參數:
    • URL (必填):要爬取的 URL。
    • depth (可選):爬取深度 (預設為 1)。
    • rules (可選):數據提取規則 (JSON 格式)。
  • 輸出格式:
    • JSON 響應,包含爬取結果或錯誤訊息。

3. 資料建模 (UML)

  • UML 類別圖:
程式碼片段
classDiagram
    class users {
        +BIGINT id
        +VARCHAR name
        +VARCHAR email
        +TIMESTAMP email_verified_at
        +VARCHAR password
        +VARCHAR remember_token
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    class password_resets {
        +VARCHAR email
        +VARCHAR token
        +TIMESTAMP created_at
    }

    class personal_access_tokens {
        +BIGINT id
        +VARCHAR tokenable_type
        +BIGINT tokenable_id
        +VARCHAR name
        +VARCHAR token
        +TEXT abilities
        +TIMESTAMP last_used_at
        +TIMESTAMP expires_at
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    class failed_jobs {
        +BIGINT id
        +VARCHAR uuid
        +TEXT connection
        +TEXT queue
        +TEXT payload
        +TEXT exception
        +TIMESTAMP failed_at
    }

    class jobs {
        +BIGINT id
        +VARCHAR queue
        +TEXT payload
        +TINYINT attempts
        +INT reserved_at
        +INT available_at
        +INT created_at
    }

    class migrations {
        +INT id
        +VARCHAR migration
        +INT batch
    }

    class crawl_tasks {
        +BIGINT id
        +VARCHAR url
        +INT depth
        +JSON rules
        +VARCHAR status
        +JSON result
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    class crawled_pages {
        +BIGINT id
        +BIGINT crawl_task_id
        +VARCHAR url
        +VARCHAR title
        +LONGTEXT content
        +INT http_status
        +TIMESTAMP crawled_at
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    class crawled_images {
        +BIGINT id
        +BIGINT crawled_page_id
        +VARCHAR url
        +VARCHAR file_path
        +INT file_size
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    class crawled_videos {
        +BIGINT id
        +BIGINT crawled_page_id
        +VARCHAR url
        +VARCHAR file_path
        +INT file_size
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    class metadata {
        +BIGINT id
        +BIGINT crawled_page_id
        +VARCHAR key
        +TEXT value
        +TIMESTAMP created_at
        +TIMESTAMP updated_at
    }

    crawl_tasks "1" -- "*" crawled_pages : has
    crawled_pages "1" -- "*" crawled_images : has
    crawled_pages "1" -- "*" crawled_videos : has
    crawled_pages "1" -- "*" metadata : has
  • 資料表解釋:
    • crawl_tasks:儲存爬取任務資訊。
    • crawled_pages:儲存已爬取的網頁內容。
    • crawled_images:儲存爬取的圖像資訊。
    • crawled_videos:儲存爬取的影片資訊。
    • metadata:儲存爬取資源的元數據。
    • 基本 Laravel 資料表:userspassword_resetspersonal_access_tokensfailed_jobsjobsmigrations
  • 關係解釋:
    • crawl_taskscrawled_pages 之間為一對多關係。
    • crawled_pagescrawled_imagescrawled_videosmetadata 之間均為一對多關係。

4. 系統架構

  • 架構圖:
程式碼片段
graph LR
    A[使用者] --> B(負載平衡器);
    B --> C{API 伺服器群組};
    C --> D[Redis 隊列];
    D --> E{隊列工作者群組};
    E --> F[資料庫];
    C --> F;
    F --> G[檔案儲存 (S3)];
  • 組件解釋:
    • **使用者:**發送 API 請求的客戶端。
    • **負載平衡器:**將 API 請求分配到多個 API 伺服器,實現負載平衡和高可用性。
    • **API 伺服器群組:**運行 Laravel 10 API 服務的多個伺服器實例。
    • **Redis 隊列:**儲存爬取任務的隊列,用於非同步處理。
    • **隊列工作者群組:**運行隊列工作者的多個伺服器實例。
    • **資料庫:**儲存爬取任務、結果和元數據。
    • **檔案儲存 (S3):**儲存圖像和影片檔案。
  • 基礎設施:
    • **可擴展性:**使用負載平衡、隊列和自動擴展組。
    • **雲服務:**使用 AWS 或其他雲端服務提供商的服務。
    • **數據效率:**使用資料庫索引、快取和檔案儲存服務。
  • 應用架構:
    • **編程語言和框架:**PHP 和 Laravel 10。
    • **請求管理:**使用負載平衡和隊列。
    • **性能優化:**使用 Laravel Telescope、快取和優化資料庫查詢。

5. 結論

本設計文件詳細說明了 Laravel 10 爬蟲 API 服務的各個方面。透過 JWT 身份驗證、RESTful API 設計、完善的資料建模和可擴展的系統架構,本服務能夠高效、安全地處理大量的爬取任務。

好的,以下是重新排版後的加分項和詳細設計考量:

加分項

  • 重複任務減少:
    • URL 正規化:
      • 在將 URL 加入隊列之前,進行正規化處理,例如:移除多餘的斜線、參數排序、轉換為小寫等,確保相同內容的 URL 被視為同一個。
    • URL 指紋:
      • 使用 URL 的雜湊值(例如:MD5 或 SHA-256)作為指紋。
      • 在資料庫中建立一個表格,用於儲存已爬取的 URL 指紋。
      • 在加入隊列之前,檢查 URL 指紋是否已存在,如果存在,則跳過該任務。
  • 避免速率限制:
    • 延遲請求:
      • 在發送 HTTP 請求之前,加入隨機延遲,避免短時間內發送大量請求。
      • 根據目標網站的響應時間和速率限制,動態調整延遲時間。
    • IP 輪換:
      • 使用多個 IP 位址進行爬取,避免單一 IP 被封鎖。
      • 可以使用代理伺服器或 VPN 服務。
    • User-Agent 輪換:
      • 隨機變更 User-Agent,模擬不同瀏覽器或使用者。
    • 遵守 robots.txt:
      • 在爬取之前,解析目標網站的 robots.txt 檔案,遵守網站的爬取規則。
    • HTTP 狀態碼處理:
      • 監控 HTTP 狀態碼,如果收到 429 (Too Many Requests) 或其他速率限制相關的狀態碼,則暫停爬取並稍後重試。
  • 數據保留:
    • 資料庫清理:
      • 使用 Laravel 的排程任務 (Scheduled Tasks),定期清理過期的爬取數據。
      • 例如:每天凌晨執行一次清理任務,刪除超過指定時間(例如:30 天)的爬取記錄。
    • 檔案儲存清理:
      • 對於儲存在檔案儲存服務(例如:AWS S3)中的多媒體檔案,也需要定期清理。
      • 可以使用檔案儲存服務的生命週期規則,自動刪除過期的檔案。
    • 資料歸檔:
      • 如果需要長期保留爬取數據,可以將數據歸檔到其他儲存系統中,例如:AWS Glacier。
  • 定期刷新:
    • 排程任務:
      • 使用 Laravel 的排程任務,定期將需要刷新的網站或網頁加入隊列。
      • 可以根據網站的更新頻率,設定不同的刷新間隔。
    • 版本控制:
      • crawled_pages 表格中,增加一個版本欄位,用於記錄網頁內容的版本。
      • 在刷新時,比較新舊版本,如果內容發生變化,則更新資料庫。
    • 條件刷新:
      • 根據特定條件,觸發網站或網頁的刷新。
      • 例如:如果網站的內容發生重大變化,則手動觸發刷新任務。

詳細設計考量:

  • 安全性:
    • 使用 JWT 身份驗證和授權機制,保護 API 端點的安全性。
    • 對使用者輸入進行驗證和過濾,防止 SQL 注入和 XSS 攻擊。
    • 限制 API 存取權限,只允許授權的使用者存取敏感資料。
  • 可擴展性:
    • 使用負載平衡器、隊列和自動擴展組,實現系統的水平擴展。
    • 使用 Redis 快取和資料庫索引,提高資料存取效能。
    • 使用非同步任務處理,減少 API 請求的響應時間。
  • 可靠性:
    • 使用雲端服務提供商的服務,確保系統的高可用性和容錯性。
    • 實作錯誤處理和日誌記錄機制,方便排查問題。
    • 定期備份資料,防止資料遺失。
  • 效能:
    • 優化資料庫查詢,減少資料庫負載。
    • 使用快取機制,減少資料庫存取次數。
    • 使用 CDN 快取靜態資源,提高網站載入速度。
    • 監控系統效能,及時發現和解決效能問題。
  • 可維護性:
    • 使用 Laravel 框架和遵循 PSR 標準,提高程式碼的可讀性和可維護性。
    • 使用單元測試和整合測試,確保程式碼的品質。
    • 編寫詳細的程式碼註解和文件,方便團隊協作。


以下是我為實現這些目標所採取的關鍵策略:

1. 非同步任務處理(隊列):

  • 我利用 Laravel 的隊列系統,將網頁爬取任務放入 Redis 隊列中。
  • 這使得 API 能夠快速響應爬取請求,而實際的爬取工作則在後台非同步執行。
  • 這種方式避免了長時間的同步請求,提高了 API 的響應速度。

2. 可擴展的系統架構:

  • 我設計了可擴展的系統架構,使用負載平衡器、隊列工作者群組和雲端服務。
  • 這使得系統能夠根據負載情況動態調整資源,處理大量的爬取任務,同時保持高效能。
  • 透過負載平衡器將 api 的請求分散到多個api伺服器。
  • 透過多個工作者群組,處理大量的爬取任務。

3. 資料庫和快取優化:

  • 我建議使用資料庫索引和 Redis 快取,優化資料存取效能。
  • 這減少了資料庫查詢的負擔,提高了資料檢索的速度。
  • 使用redis 快取熱門的爬取資料。

4. 速率限制和錯誤處理:

  • 我提供避免速率限制的策略,例如:延遲請求、IP 輪換和 User-Agent 輪換。
  • 我實作了錯誤處理機制,監控 HTTP 狀態碼,並在發生錯誤時進行重試或記錄日誌。
  • 這些措施確保了爬取的穩定性和可靠性,同時避免對目標網站造成過大的負擔。

5. 程式碼優化:

  • 我提供的程式碼經過優化,使用了 Guzzle 和 Symfony DomCrawler 等高效能的程式庫。
  • 這確保了網頁內容的快速下載和解析。
  • 在程式碼裡面,圖片以及影片的下載,使用非同步的方式處理。

總結:

透過以上策略,我提供的服務能夠高效地爬取單個網頁或整個網站,提取結構化數據,同時確保合理的響應時間。您可以根據您的具體需求,進一步調整和優化這些策略,以達到最佳的爬取效能。

沒有留言:

張貼留言