--- tags: interview --- ## 更新紀錄 2024-01-13: - [x] 補充了二面提到的一些問題。 2024-01-11: - [x] 1. 直接將私人 Repo 都打開了,感覺沒時間整理,而且其實也沒什麼特別的技術。以前開發的時候有些環境變數直接埋在 Code 沒有抽到 .env,請見諒。 - [x] 2. 面試官問到「為了防止重送在前端會採取什麼防禦」,關於「5 秒盾有什麼破解方式」,補充在文末。 - [ ] 3. 應該更詳盡陳述發現並克服過哪些困難。 ## 目錄 - [前言](https://hackmd.io/oeH89T61RQOsUZiT-tUYtw?both#%E5%89%8D%E8%A8%80) - [在爬蟲方面的工作經驗](https://hackmd.io/oeH89T61RQOsUZiT-tUYtw?both#%E5%9C%A8%E7%88%AC%E8%99%AB%E6%96%B9%E9%9D%A2%E7%9A%84%E5%B7%A5%E4%BD%9C%E7%BB%8F%E9%AA%8C) - [關於爬蟲我覺比較重要的事情](https://hackmd.io/oeH89T61RQOsUZiT-tUYtw?both#%E5%85%B3%E4%BA%8E%E7%88%AC%E8%99%AB%E6%88%91%E8%A7%89%E6%AF%94%E8%BE%83%E9%87%8D%E8%A6%81%E7%9A%84%E4%BA%8B%E6%83%85) - [面試的問題匯整](https://hackmd.io/oeH89T61RQOsUZiT-tUYtw?both#%E9%9D%A2%E8%AF%95%E7%9A%84%E9%97%AE%E9%A2%98%E6%B1%87%E6%95%B4) ## 前言 ~~大部分的作品都擺在私人的 Repo,有些因為年代久遠需要整理,不太好意思直接擺出來讓別人看到,Demo 的時候可以看一下,但請不要驚慌 🙈。~~ ## 在爬蟲方面的工作經驗 ### 1. 統一發票中獎號碼(2015) - jsdom(Javascript) 學校的 Android App 作業,我用 PhoneGap(現在叫 Cordova) + jsdom 做了一個獲取中獎號碼有對獎功能的小 App。 ### 2. 水情監控 (2016) - phantom.js(Javascript) 在 Selenium/Puppeteer 出現以前,就用過 phantom.js 獲取水情監控即時影像的截圖。 > 當時有朋友的工作是要定期將多處水情監控的影像匯整成一份日誌。 ### 3. 雅虎電影、本日星座運勢、匯率(2017) - SimpleXML + XPath(PHP) - Cheerio.js(Javascript) - File Cache & Throttling(Javascript) 基於好玩做了一個 LINE Bot,在上面整合了本週熱門電影(PHP + SimpleXML + XPath )、本日星座運勢(Cheerio.js)及近 15 分鐘美金對台幣、台幣對日元匯率查詢的功能。 > 當時用匯率的 API 有每個月的免費額度(忘記是 3000 次還是多少),所以以 15 分鐘為單位作快取避免請求過於頻繁。 ### 4. 奧圖碼網站改版(2018) - Regex(PHP) 將原本靜態頁面內容抓取出來改成以 WordPress 頁面的內容存取。 > 因為涉及到多個語系的網站,且要將取得的頁面內容盡量整合,當時寫的 Regex 較複雜。 ### 5. 台北體育館羽球場自動預約爬蟲(2020) - webdriverio(Javascript) - tesseract(Javascript) - jimp(Javascript) - nexe(Javascript) https://gitlab.com/z411392/tms-venues-booking 因為網站有 Captcha 保護,而且這時候還不知道可以用 Yolo。破解 Captcha 的方法是用 jimp 作簡單的影像處理,再透過 tesseract 對處理後的 Captcha 作 OCR。 > 成功率感覺 80% 左右,所以後來放著了。 ### 6. 台北市、新北市土地公告現值爬蟲(2022、2023) - webdriverio(Javascript) https://gitlab.com/z411392/assessed-present-value-for-new-taipei-city https://gitlab.com/z411392/assessed-present-value-for-taipei-city 一開始先用 webdriverio 開發。 - puppeteer(Javascript) https://gitlab.com/z411392/apv-new-taipei https://gitlab.com/z411392/apv-taipei 後來因為改用 puppeteer (考慮到沒有要在 chrome 以外的瀏覽器上執行且寫起來較順手) - puppeteer(Dart) https://gitlab.com/z411392/taipei_apv https://gitlab.com/z411392/new_taipei_apv 最近又實驗性地用 Dart 再改寫過(也能編譯成 binary,有 Stream 類別,但後來也沒用上 😅)。 ### 7. 第二類地籍謄本解析器、第二類建物謄本解析器(2022、2023) - xlsx(Javascript) - pdf-parse(Javascript) https://gitlab.com/z411392/land-registration-data-extractor https://gitlab.com/z411392/building-registration-data-extractor 這邊是很生硬的根據 PDF 內容的格式作解析,然而拿到的 PDF 格式差異可能滿大的,這時候會解析失敗。 涉及到 xlsx 讀取、寫入(批次作業)以及對 PDF 的解析。 - pymupdf(Python) - python-dotenv(Python) - openai(Python) - aiofiles(Python) - XlsxWriter(Python) https://gitlab.com/z411392/land_registration_transcripts_parser https://gitlab.com/z411392/building_registration_transcripts_parser 為了更容易編譯成 binary 後來用 Python 改寫過。 目前正在將擷取內容的工作改成用 OpenAI,而其中一部分 PDF 埋的文字圖片改用雲端的 OCR 服務辨識。 並且打算部署到 Cloud Run,在 Pub/Sub 後執行(分階段)。 ### 8. 課程教學影片下載器(2022) https://gitlab.com/z411392/course-video-saver - pyppeteer(Python) 這一年我在上勞動部委外的職訓課程。因為課程在一段時間後會下架,所以特別寫了一隻爬蟲將課程影片下載下來。 ### 9. 天氣預報爬蟲、PCHome 商品搜尋結果爬蟲(2022) https://colab.research.google.com/drive/1bted6jeIysqXIfdwyVbL6LBKPZry5jzB - request(Python) - beautifulsoup(Python) 課程期間,除了直接用 request 獲取 API 回傳結果外,也學習了用 beautiful soup 解析 HTML 的內容。 #### 10. 影像處理( 2022) 課程期間學習了簡易的影像處理和文數字辨識(去浮水印、去雜訊、獲取輪廓、影片圖像讀取)。 [去浮水印](https://colab.research.google.com/drive/1Em-Mqn7S_E9bEpvvyfzkJZLurQlJNXFL#scrollTo=miCc3RFL6OsB#cell-miCc3RFL6OsB)、[去雜訊](https://colab.research.google.com/drive/1Em-Mqn7S_E9bEpvvyfzkJZLurQlJNXFL#scrollTo=HqIvd3u6-wqQ#cell-HqIvd3u6-wqQ)、[獲取輪廓](http://cell-iRoJvhwn5Ogq)、[影片圖像讀取](https://colab.research.google.com/drive/1Em-Mqn7S_E9bEpvvyfzkJZLurQlJNXFL#scrollTo=GybXJrffqxMi#cell-h1uMTq3Pqzxo)等。 ### 10. Yandex 圖片搜尋結果下載器(2022) https://gitlab.com/handsome-man-classifier/yandex-crawler https://gitlab.com/handsome-man-classifier/yandex-downloader https://gitlab.com/handsome-man-classifier/yandex-cropper https://gitlab.com/handsome-man-classifier/face-clustering - aiohttp(Python) - aiofile(Python) - cv2(Python) 課程期間,學習了人臉特徵抽取(FaceNet)及 KNN 方法。我自己私下測試了一下各種將人臉特徵向量自動聚類的方法,也測試了 PCA、TSNE 將向量降維量看看測降維後向量相近的程度。 > 後來有試過用隨機投影將特徵向量轉為 16 進位的一串 Hash(但同一個人不同人臉還是可能算出不同 Hash)。 ### 11. 聲音轉文字測試(2022) - moviepy(Python) - speech_recognition(Python) - pydub(Python) https://gitlab.com/z411392/audio-extractor/-/blob/master/audio-extractor.py?ref_type=heads > 轉換的結果不如預期,所以先擺著。 ### 12. 三民輔考考古題下載(2022) - aiofile、aiohttp(Python) - beautifulsoup4(Python) - python-dotenv(Python) - pygtrie(Python) https://gitlab.com/z411392/3people-exam-downloader > 比較特別的是用 trie 當資料結構用來快速尋找考題。 ### 13. Google 圖片搜尋結果下載器(2022) - pupeteer(Python) https://gitlab.com/z411392/google 課程期間,為了團體專題需要,寫了爬蟲來抓取搜尋結果的圖片。 因為介面上是 Infinite Scroll 的關係,再讀取分頁時要特別花心力寫 Javascript 控制瀏覽器行為以取得內容。 ### 14. Excel 密碼破解器、Wifi 密碼破解器(2022) https://colab.research.google.com/drive/15iogDNnkgoIb8CTHjcJnhO-OEUOHvS-M https://gitlab.com/z411392/wifi-cracker > MacOS 切換重試 Wifi 會用比較長的時間,所以整個破解過程非常緩慢。 ### 15. instagram 推薦內容下載器(2023) https://gitlab.com/z411392/instagram_downloader - puppeteer(Dart) 因為學習了 Dart/Flutter,基於 Dart 的語言特性(有個 Stream 類別)實驗地寫一個爬蟲看看。 > 發現 Mac 上的排程在待機的時候不會執行。而且因為沒有能分別出抓到的圖片哪些是廣告,哪些是推薦的內容所以就擺著了。 ### 16. 食品營養資料集(2023) - Google App Script - Google Spread Sheet - ~~OR Tools(Python)~~ https://docs.google.com/spreadsheets/d/1vyMQfFPw45-QUExNZBWBhRfLlnflxYXZD8ObYv9mWQk/edit#gid=1222427181 本來想實驗用 OR Tools 規劃每天的飲食菜單,先用政府公開資料作了一個 Spreadsheet,後來感覺複雜可能沒時間做出來就先放著了。 ### 17. 社交 APP(Hornet)人臉資料庫(2023) - QDrant(向量資料庫) - oclif(Typescript) - face-recognition(Python) - dependency_injector(Python) - aiofile、aiohttp(Python) https://gitlab.com/z411392/horny_at_cli https://colab.research.google.com/drive/17Q2JTwWAvWtX3BzoH0Pto-4mbMrikTAH#scrollTo=VucYJcEgC5EW https://colab.research.google.com/drive/1Gu_Z15oWLPSfDznPS01At47jCtPP6EPs 實驗將人臉辨識得到的特徵向量存到 QDrant 作搜尋。 ### 18. 偵測色情圖片(2023) https://gitlab.com/z411392/nsfw_detector https://gitlab.com/z411392/open_nsfw 想用這個工具來整理電腦裡面的圖片。 > 發現還是會有偵測錯誤的情形(非色情認定為色情、色情認定為非色情都有)。 ### 19. 對 2000 年以來的月報酬率資料作 STL 分解(2023) https://colab.research.google.com/drive/1omRshwevr7-7he9KfSFjAdDa1BgOAO7Q 雖然沒有時間序列分析的數學基礎,但是簡單的函數呼叫還是會的 🤣。據說這樣作之後能看到排除季節性、雜訊影響的趨勢。 ## 關於爬蟲我覺比較重要的事情 1. Python 可以寫 async、await,應該要用 Async Queue 將不同階段的 Producer、Consumer 切分出來,盡量減少無謂的 IO 等待。 2. 因為 GIL 的限制,需要 CPU 的操作例如影像處理、計算,應該要傳遞給 Process Pool 處理。 3. Javascript/Typescript、Python、Dart 都能寫 Puppeteer 的腳本。Python 和 Dart 比較容易將寫好的程式編譯成 binary。套件的資源在 Python 上還是比較豐富。 ## 面試的問題匯整 ### 一面 1. 為了防止重送在前端會採取什麼防禦 乍聽之下以為是在介面上應該做什麼(停用表單的發送按鈕),後來想想,問的應該是「作為網站維運方如果想要採取防禦措施應該做什麼事情」。 這時應該做的事情是在表單上附帶一個事先由 Server Side 產生的 Nonce,在傳送表單到 Server Side 時,去檢查這個 Nonce 是否存在、是否正確。 最陽春的做法應該是每個使用者有各自唯一的 Nonce,在某些操作後這個就讓這個 Nonce 更新(要避免窮盡嘗試和暴力破解)。 然而實際上未登入的使用者也可能會面臨表單重送的問題。在這個情形下,頁面要預先產生 Device ID,而基數關係要改為每一個 Device ID 有個各自的 Nonce。 > 之所以要預先產生 Device ID 是因為即便用上 User-Agent 和 Public ID,仍不能保證能產生裝置唯一的識別碼(例如共用一個區域網路使用同一種電腦和同一種瀏覽器)。 如果 Nonce 的數值是完全隨機的(不是由Device ID 和某個 Timestamp 推導出來),就應該另外存在資料庫裡。 已上是我自己先胡思亂想得到的想法。 Stack Overflow 上的[這則討論](https://stackoverflow.com/questions/4145531/how-to-create-and-use-nonces)應該是實現了 Wiki 上的做法:  這裡可以看到兩個不同的地方: 1. 驗證 Nonce 時,驗證的不是 Nonce 的內容,而是 Nonce 和所傳遞資料的 Hash。 > 其實這邊我有點不明白。想到一個的理由是,如果驗證的不是 Hash,那麼攻擊者可以拿同一串 Nonce 不停的試,直到某天 Server Side 產生的 Nonce 湊巧和攻擊者用的這串 Nonce 相同時(但理論上 Nonce 設得稍微長一點就會讓這件事情很難發生)。 2. 多加了 CNonce,並要求 CNonce 盡量每次都不一樣。 > 這使得即便有了 Nonce 和對一系列偽造內容的 Hash,仍不能從 Hash 反推出偽造的內容是什麼。並且可以監測同一串 CNonce 的使用次數(但是你都能拿到 Nonce 和 Hash 了會拿不到內容嗎🤔)。 ### 一面 2. 5 秒盾有什麼破解方式 先看到[這篇](https://34e.cc/1011),看下來原理是要手動維持跟 CloudFlare 的 Cookie Session 連線。 實際上打開 gitlab 驗面。 在 CloudFlare 驗證結束後,這時候逐一的刪除某個欄位,並且重新打開畫面,看看哪個 Cookie 消失會讓網站將我們重新導向 CloudFlare。這裡發現 `cf_clearance` 可能是關鍵。  使用 Modify Header Value 這樣的外掛,將 `Cookie=cf_clearance=Bxs92Zm2rN7KE.UGRfiWXxZDNX3RNRGA6L.XEM9DrKI-1705075142-0-2-42dbaca.a3861ddb.532ce52a-160.0.0` 放置在 Header 中。清除 Cookies 並重新整理頁面,發現不會再被轉向 CloudFlare 了。  為了讓自動化作業之後都能夠順利,應該要瞭解整個過程背後,它是如何更新 `cf_clearance` 這個值的。 先打開一個新的分頁,先啓用 Preserve log 功能再貼上網址:    這裡發現: 1. 實際上 cf_clearance 是由 gitlab 提供的。 2. CloudFlare 的頁面是一次性的頁面(再次進入就無法瀏覽)。 3. CloudFlare 在完成非爬蟲驗證後,透過 post 方法將驗證結果再回傳給 gitlab。gitlab 應該是再透過 Server To Server 的 API 呼叫驗證並產生 `cf_clearance`。 如此一來產生 cf_clearance 的過程勢必不會是單純的 API 呼叫了。 至於原本文章中提到的 app_session,如果 cf_clearance 欄位是具有時效性,且會在每一個時間後的 Request 自動更新的話,可以透過 Crontab 定期發送 Request 並解析 Cookie 來更新它的值,這樣只有第一次設定值的時候會麻煩些。 不過也可能 cf_clearance 是無法在一段時間後自動更新必須將驗證過程重跑一次的,這時候就只能祈禱通過 CloudFlare 驗證的 Puppeteer 腳本好寫(如果會遇到 Recaptcha 就沒轍 🙈)。 ### 二面 1. 在影音平台公司所作的項目擴展都是些什麼? 每個項目的會員機制(要特別加值 VIP)、點數機制(A 類會員不用點數、B 類會員折扣 89 折之類)不太一樣。 也有內容上的不同(例如其他項目都是視頻但這個項目是有聲書)。 ### 二面 2. 將資料同步到 Elastic Search 的這一段你們是怎麼實現的? 項目一開始會用 cli 同步過一次,之後每次後台編輯也會同步一次。知道 CDC 的概念(Firebase、Mongo 都能很輕易做到),但是舊項目沒有用上。 不過有個項目同步作業比較複雜,有先將同步工作 Pending 到 Redis,再慢慢執行。 > 回饋:沒有透過 CDC 切分出去影響的倒不是可讀性的問題,而是會影響之後的權責分工。 ### 二面 3. Nuxt 和 Vue 有什麼區別? Nuxt 規劃好一系列的資料夾、檔案的規範或者說擺放方式,極大化減少了 Routing、Compiling 設置工作。 其他⋯說不上來,就是比較方便 🤣 ### 二面 4. React Native 和 Flutter 有什麼區別? React Native 保留了從 Web 過渡過來的一些特性(Web Components、Life Cycle & Hooks)。 Flutter 和 React Native 中間 Rendering 都是 Native 的,除此之外想不到什麼差別 😂。 > 回饋:一個是需要的 Stacks,熟悉 React 較容易從 Web 遷移過來(成本較小?)。另外 React Native 中間還是多了一個轉譯 JS 的過程。 ### 二面 5. 在廣告行銷公司開發過什麼樣類型的網站? 主要是各類行銷用的活動網站(抽獎、集點卡),另外有一些會員卡註冊、綁定的申請。 ### 二面 6. 應對高流量時活動網站如何做好準備? 最常見的事情是基礎設施例如資料庫最大連線數的設置。 應用層這邊能做的事是讓服務能夠 Scaling(譬如說 Session 應該要存放在共用的 Redis 而不是某個主機上的 File System),每個服務要能 Throttling。 應該設法讓流量盡可能少(壓縮、合併靜態檔案)。 > 回饋:比較想聽的是前面的 Load Balancer 如何安排連線作業給底下的每一台主機。靜態檔案問題倒是容易,直接掛到 CDN 即可。重要的事情是能靜態回應的頁面就不要動用計算資源,我們之前做的抽獎網站是這樣,不曉得你們是不是也這樣做?(沒有,我們直到抵達頁面都還是會持續跟資料庫要資料 😅) ### 二面 7. CRM 跟 ERP 的區別是什麼? 我的印象裡,ERP 比較像進銷存管理的後台,比如說對用球用品的庫存、定價/售價、代理商分潤管理。 CRM 做的事情比較像是設定一些活動,蒐集資料,根據設置的條件派發優惠(集點完成、生日)或通知。 ### 二面 8. 分布式爬蟲如何避免重復執行同一任務的問題? 我的想像是 Pub/Sub。Master 透過 Pub 將任外派發出去,Slave 透過 Sub 來執行任務。在我想像中應該是能設定一次 Pub 只會有一個 Slave 收到任務,如果發生錯誤任務無法完成會進入重試過程。但如果真的有可能會遇到同一個任務,應該是在每次任務開始前,先檢查資料庫裡面這個任務的執行狀態,並改為執行中(例如 Pending -> Processing),在任務結束後再將狀態改為其他(例如 Processing -> Finished / Failed)。 ### 二面 9. 網站方如何防禦 IP Pool 之類的工具? 我記得 Server Side 應該還做不到區分每一個 Request 來源主機的 Mac Address。以前有過的做法是,透過 Public IP 和 User Agent 去產生 Device ID,然後計算同一個 Device ID 被多少 Public IP 使用以及同一個 Device ID 在某段時間內發出過多少 Requests(但是除非 Device ID 產生過程成本很高,否則其實對防禦 IP Pool 也沒什麼幫助)。 ### 二面 10. 如何在 Request Limitation 下盡可能取得更多的資料(更連續、實時)? 要將 Requests 盡可能分散、Concurrently 的發送出去。可能會借助到 Promise Pool 之類的工具(不知道 Python 上叫什麼)。 > 回饋:不一定是什麼工具,要的話自己寫都可以對吧?(沒錯~)
×
Sign in
Email
Password
Forgot password
or
By clicking below, you agree to our
terms of service
.
Sign in via Facebook
Sign in via Twitter
Sign in via GitHub
Sign in via Dropbox
Sign in with Wallet
Wallet (
)
Connect another wallet
New to HackMD?
Sign up