ferret 爬取動態網頁

pardon110發表於2019-12-15

動態網頁常用js來載入資料,使用宣告式語言fql,可輕鬆獲取點選,下拉等一系列需要互動後渲染的頁面資料
夠浪的ferret足夠簡單, 讓會sql,瞭解css,知道點go的同學,很方便的用編碼或命令列形式抓取動態網頁內容。

selenium

selenium真心好用,但太重。誇它好用,是因為不像scray一個頁面情況沒考慮到,它就給掛了,給定目標網站使用者讓怎麼跑就怎麼幹。說它重是因為耗資源,若僅作爬蟲抓取,為什麼要開一個瀏覽器,又不是真要用介面。
fql進行動態網頁抓取

cdp

chrome debug protocol 谷歌瀏覽器除錯協議,簡稱cdp

用過chrome瀏覽器的F12,也就是devtools,其實這是一個web應用。當你使用devtools的時候,瀏覽器本身會作為一個服務端,而你看到的瀏覽器除錯工具介面,其實只是一個前端應用,在這中間通訊的,就是基於websocket的cdp,一個讓devtools和瀏覽器核心交換資料的通道。

selenium -> webdriver -> chromedriver  -> cdp --> fql
  • cdp獲取頁面網路資料
  • 用cdp獲取頁面載入時間
  • 用cdp拿到自動化測試後的js覆蓋率資料並展示
  • 通過遠端機器除錯無頭瀏覽器

fql

ferret特定領域的宣告式程式語言fql,簡單直觀。
輸入關鍵字 --> 點選搜尋按鈕 --> 用css 選擇器選擇節點 --> 迭代處理內容 --> 返回內容

// baidu.fql

LET bd = DOCUMENT("https://www.baidu.com/", {
    driver: "cdp",
    userAgent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.87 Safari/537.36"
})
// 互動操作
INPUT(bd, 'input[name="wd"]', @wd)
CLICK(bd, '#su')
WAIT(RAND(1000))

FOR result IN ELEMENTS(bd, '#content_left')
    LIMIT 3
    LET title = INNER_TEXT(result, 'h3')
    LET description = INNER_TEXT(result, 'div.c-abstract')
    RETURN {  title, description }

上述 @wd 為輸入型引數,同sql中的位置引數一個道理。
{ title, description } 是fql語法的一個特定,同es6中的物件解構賦值
RETURN 關鍵字在fql與php,python 中的生成器yield一樣的意義,只是帶值返回,可以重新返場

usage

  1. 安裝ferret,建議使用go1.13以上版本,開啟國內映象代理,當然你本機也得裝chrome瀏覽器

    go get github.com/MontFerret/ferret
  2. 開啟chrome的cdp服務例項,記住使用無頭模式

    chrome.exe --remote-debugging-port=9222 --headless
  3. 匯入baidu.fql,ferret使用的預設埠是9222

    D:\code-base\gomod\colly>ferret --param=wd:\"golang社群\"  > baidu.txt
  4. 開啟檢視結果,類似於下面這樣的格式

    [{"description":"Go語言中文網,中國 Golang 社群,Go語言學習園地,致力於構建完善的 Golang 中文社群,Go語言愛好者的學習家園。分享 Go 語言知識,交流
    使用經驗","title":"首頁- Go語言中文網 - Golang中文社群"}]

other

ferret 目前還處於開發階段,但其不僅僅這些,比如cookie,快照截圖,圖片下載,代理等等新功能已經處於測試。目前版本是v0.9.0, 穩定版本很快釋出。上面示例僅展示了命令列形式,事實上它還可以嵌入到golang編碼,產生各種好玩的用法。

相關文章