Paper Crawler (download pdf)

created_at: 2024/11/12 23:30:00

cover image

一個微服務架構實作的論文爬蟲系統,這個系統每個服務都可以單獨運作、部署,方便擴充支援的網站。


為什麼會有這個服務

...有人有需求,於是我想了想,這樣可以解決問題,然後我想說當練手,於是這個服務就誕生了。


Demo

大概說明一下:

  • 一開始要輸入一串預先產好的 token 做最最基本的防禦(因為畢竟還是有 public 到網路上,雖然沒有給其他人)
  • 爬取過程有機會失敗,若失敗會有相應的錯誤訊息(timeoutsomething went wrong等等),若是 something went wrong 的話,有可能的問題很多,所以要看一下 log 才能知道是什麼問題,但不方便透露給前端,所以就只有 something went wrong 這樣的訊息,但失敗不影響服務的運作
  • 爬取成功後,可以預覽或是下載 PDF 檔案
    • 預覽是打開新分頁(blob)顯示 PDF 檔案
    • 下載是直接下載 PDF 檔案(檔名會正確)
    • 註1
  • 使用者重新整理頁面會保留當前的狀態,但如果使用者整個 session 都關掉,就會回到最初的狀態
    • 這邊使用者定義為同一個 real ip

註1: 為什麼不預覽然後讓使用者直接 Ctrl + S 呢? 為什麼還要多做一個下載的按鈕? 簡短來說是為了提高下載的 UX,細節的話主要是因為我的檔案也有受到 token 的保護,所以除非我在後端特別做一些比較麻煩的處理,不然如果透過單純預覽的方式下載,檔名會是 blob,這樣對於使用者下載的 UX 來說不太好,所以額外提供一個下載的按鈕,就可以透過 Content-Disposition 來取得正確的檔名。

  • 其實有兩個下載的按鈕,下拉選單本身也是

Source code 目前沒辦法公開,有兩個原因:

  1. 我還沒整理好 code
  2. 畢竟是這種服務,公開讓大家去爬蟲的話,好像不太好(雖然需要帳號)

但我可以放上架構和一些實作流程(?)


Tech Stack

  • Frontend: Svelte 5Tailwind CSSEventSource
  • Backend: GingRPCPythonRabbitMQ
  • CI/CD: Github Actions

沒有資料庫,因為並不打算做資料的儲存,重啟服務後又和乾淨的一樣。


宏觀的系統架構

架構圖

這個架構圖省掉了一些細節,主要是呈現可以輕易的擴充服務的部分。

另外 Auth 的部分其實可以與 Audio 服務整合成一個服務,因為在這個系統中並沒有其他服務去使用 Audio(聲音轉文字)的功能,但為了當作練習(?)所以刻意將它分開。

接著我們來看看細節,還有為什麼可以方便擴充服務。


實作流程

既然是爬蟲服務,最主要的當然就是爬取的流程,所以先附上爬取流程的圖片。

爬取流程

這些爬蟲服務的流程都是一樣的,只是不同的服務有不同負責的網站,而每個服務都會去消費 RabbitMQQueue,當有新的 URL 進來時,就會去爬取資料。

爬取的流程,一開始會先去初始化 WebDriver,然後以 MultiProcess 的方式去執行爬蟲的流程,這樣還可以來監聽執行的時間,如果超過一定時間就會強制結束,避免爬取的時間過久。

而爬取的細節則與流程圖一樣,比較重要的是當爬蟲結束後會將登入的狀態保存下來,這樣下次爬取時就不用再重新登入,這樣不只可以節省一點時間以外,還可以防止被網站鎖住(?)

接著還會需要 Auth 的部分

Auth

Auth 的部分其實和爬蟲的部分差不多,只是在多了 Retry 的機制,避免 Audio 服務去得到的驗證碼有誤,這樣就可以重試。

然後也一樣有儲存登入狀態的機制,避免每次都要重新登入。


為什麼可以方便擴充服務

每個爬蟲服務都是獨立的,所以只要新增一個服務,然後將一樣去監聽 RabbitMQQueue,就可以開始爬取資料。 (並且建立屬於自己的 Queue)

另外爬蟲的部分有實作一個抽象類別並實作 Template Method,這樣可以讓每個服務去實作自己的爬取流程,也不用擔心 AuthTimeout 等等的細節,只要聚焦在自己負責的網站身上,也就是上方流程圖當中 Start crawling documents 的部分。

後端也會透過 RabbitMQAPI 來取得目前的 Queue 來得知目前支援的網站,這樣就可以在前端動態的顯示支援的網站,並且在使用者送出 URL 時,也可以檢查是否支援。

最後是部署也是獨立的,各服務有自己的 Environment 設定、Dockerfile


方便擴充服務的驗證

2024/12/12更: 時隔一個月,新增服務支援 Springer 平台,前後端一行 code 都沒動,只微調了 docker-compose(加一個服務) 與 CI 的一個 job (確保生成的程式碼由程式產生(grpc))。


未來展望

這個服務的重點大概就這些了,如果未來有時間會想做的更完整一些,例如:

  • 使用更好的服務發現的方式(etcd),讓服務可以自動加入,也能增加冗餘,增加服務的可用性 (目前是Docker Compose)
    • 還可以在前端顯示服務的狀態
  • 增加資料庫,讓爬取的狀態更完整並即時顯示在前端
  • 前端的 Retry 機制 (因為沒有 DB,實在很不想每個去跑 for
  • 增加 Rate Limit 的機制 (因為目前沒有公開,所以沒有實作;若公開的話,這個機制是很重要的)
    • 如果公開也許還可以做 quota 的機制來收費
  • 使用 Kubernetes 來部署: 來達到更高的穩定性
  • 使用 Prometheus + Grafana 來監控服務

暫時想到的就這些(?) 可能有忘掉的地方

主要還是礙於時間論文的壓力,所以這個服務就先這樣了,有機會再來完善。(如果未來有機會沒事做沒題材的話)