iT邦幫忙

第 12 屆 iT 邦幫忙鐵人賽

DAY 15
2
AI & Data

行銷廣告、電商小編的武器,FB & IG 爬蟲專案從零開始系列 第 15

【Day15】 json x 爬蟲 = 瑣事自動化,生命應該浪費在美好的事情上

即使客戶不懂程式,你也可以讓他學習一點工程師的知識

/images/emoticon/emoticon16.gif 我們要請客戶將爬蟲的網址列表填寫到什麼檔案呢?

專案在需求規格中有一條是在自己的電腦執行,在分析完各種檔案格式的優缺點後我決定使用json格式:

  • txt
    • 優點:在所有作業系統中都能夠打開做編輯
    • 缺點:格式難以律定,只要使用者多個空格、表點符號...都容易造成程式的誤判
  • excel
    • 優點:這是對使用者而言最友善的一種編輯器了,視覺化良好、操作友善
    • 缺點:不是所有人電腦都有安裝 excel 編輯器(像我朋友就沒有)
  • json
    • 優點:在所有作業系統中都能夠打開做編輯,key-value 的格式易於理解、程式可直接讀取
    • 缺點:使用者需要花幾分鐘時間理解 json 格式的規則

/images/emoticon/emoticon12.gif 今日目標

1. 了解 json 格式與基本規則,並建立 json 格式的粉專清單

1.1 json 格式與基本規則
1.2 在專案中建立 json 格式的粉專清單

2. 讓程式讀取 json 裡面的資料進行爬蟲

2.1 在專案引入 json 檔案
2.2 批量爬蟲程式撰寫


1. 了解 json 格式與基本規則,並建立一份 json 格式的粉專清單

今天說的這個部分應該是大部分小編最關心的,要每天手動瀏覽那麼多的粉專想想都很崩潰
所以要來跟大家介紹的一個很棒的文本格式:json (JavaScript Object Notation) ,他能幫助我們批量爬蟲,同時也是網頁 api 最常見的一種回傳格式

1.1 json格式與基本規則

json 可以包含 object (物件)array (陣列)

  • 物件
    • 為 key-value 的格式,用{...}包起來
      { "key" : "value" }
      
      { "姓名" : "寶寶不說" } //通常用於描寫一項屬性的數值
      
    • 多個物件使用 , 做為分隔
      { "key" : "value" , "key" : "value" }
      
      { "姓名" : "寶寶不說" , "性別" : "不明" } //多個物件可表達一個東西的多種屬性
      
  • 陣列
    • 多個 value 之間使用 , 分隔,用[...]包起來
      [ value, value ]
      
      // 陣列與物件裡面value可以使用多種資料型態如下
      [ 0 , { "傳奇寶寶" : null } , "string" , false , ['test'] ]
      

1.2 在專案中建立json格式的粉專清單

建構邏輯:

  1. 我們有許多粉專需要去追蹤,所以最外層會用 陣列(array)
  2. 每個粉專都有自己的屬性(title為粉專名稱、url為粉專網址),所以陣列裡面的 value 採用 物件(object)
    [
        {
            "title": "粉專A",
            "url": "粉專A連結"
        },
        {
            "title": "粉專B",
            "url": "粉專B連結"
        }  
    ]
    

在專案建立的步驟:

  1. 在專案資料夾中建立 fanspages 的資料夾,專門存放粉專頁面爬蟲要使用的json檔案
  2. fanspages 資料夾中新增 ig.json、fb.json 這兩個檔案,並依照上述json結構填上你要爬蟲的資訊
  3. 你可以先複製下方範例做測試(筆者是以下貼圖的狂熱愛好者,歡迎一起追蹤按愛心XD)

ig.json

[
    {
        "title": "寶寶不說",
        "url": "https://www.instagram.com/baobaonevertell/"
    },
    {
        "title": "松尼",
        "url": "https://www.instagram.com/sweethouse.sl/"
    },
    {
        "title": "麻糬爸",
        "url": "https://www.instagram.com/mochi_dad/"
    },
    {
        "title": "好想兔",
        "url": "https://www.instagram.com/chien_chien0608/"
    },
    {
        "title": "ㄇㄚˊ幾兔",
        "url": "https://www.instagram.com/machiko324/"
    }
]

2. 讓爬蟲程式讀取 json 裡面的資料

2.1 在專案引入 json 檔案

  • 引入 json 檔案時請注意相對路徑,建議先用 console.log 確認是否有正確引入
  • 因為這個檔案是人工撰寫,可能會不小心複製到重複粉專,所以使用 filter 來過濾
let fanpage_array = require('../fanspages/ig.json');
//過濾掉重複的粉專頁面,減少資源浪費
fanpage_array = fanpage_array.filter((fanpage, index, self) =>
    index === self.findIndex(f => f.url === fanpage.url)
)
console.log(fanpage_array)

2.2 批量爬蟲程式撰寫

  • 將前往粉專頁面與爬蟲的部分用 for/of迴圈 包起來(因迴圈內用到 async/await),讓他依序前往粉專頁面抓資料
    for (fanpage of fanpage_array) {
        // 撰寫你要對fanpage做的事       
    }
    
  • 我們要當個好爬蟲,每個頁面設定爬蟲停留 3-6 秒,不要因為自己的爬蟲造成別人伺服器的負擔

    這裡我們使用Math.random()取得區間亂數

    await driver.sleep((Math.floor(Math.random()*4)+3)*1000)
    
  • 統整後完整程式如下

    crawlerIG.js

    let fanpage_array = require('../fanspages/ig.json');
    //過濾掉重複的粉專頁面,減少資源浪費
    fanpage_array = fanpage_array.filter((fanpage, index, self) =>
        index === self.findIndex(f => f.url === fanpage.url)
    )
    const ig_username = process.env.IG_USERNAME
    const ig_userpass = process.env.IG_PASSWORD
    const { By, until } = require('selenium-webdriver')
    exports.crawlerIG = crawlerIG;
    
    async function crawlerIG (driver) {
        const isLogin = await loginInstagram(driver, By, until)
        if (isLogin) {
            console.log(`IG開始爬蟲`)
            for (fanpage of fanpage_array) { // 用迴圈爬蟲每個粉專
                let trace = null
                const isGoFansPage = await goFansPage(driver, fanpage.url)
                if (isGoFansPage) {
                    //每個頁面爬蟲停留3~6秒,不要造成別人的伺服器負擔
                    await driver.sleep((Math.floor(Math.random() * 4) + 3) * 1000)
                    trace = await getTrace(driver, By, until)
                }
                if (trace === null) {
                    console.log(`${fanpage.title}無法抓取追蹤人數`)
                } else {
                    console.log(`${fanpage.title}追蹤人數:${trace}`)
                }
    
            }
        }
    }
    .//後面程式一樣
    .
    .
    

/images/emoticon/emoticon07.gif 執行程式

  1. 在專案資料夾的終端機(Terminal)執行指令
    yarn start
    
  2. 確認畫面執行順序如你預期:Instagram自動登入 → 依序跳轉到指定帳號 → Facebook自動登入 → 依序跳轉到粉絲頁 → 關閉
  3. 大概裝完一壺水的時間後,你就能看到 FB & IG 的追蹤人數嚕~
    https://ithelp.ithome.com.tw/upload/images/20200928/20103256FC6SHseDcH.png

搭配上json後有沒有覺得自己功力大增XD,上面的是IG的範例,大家可以自己嘗試看看FB部分的如何改寫喔~


ℹ️ 專案原始碼

  • 今天的完整程式碼可以在這裡找到喔
  • 我也貼心地把昨天的把昨天的程式碼打包成壓縮檔,你可以用裡面乾淨的環境來實作今天json改寫的部分喔
    • 請記得在終端機下指令 yarn 才會把之前的套件安裝
    • windows需下載與你chrome版本相同的chrome driver放在專案根目錄
    • 調整.env檔
      • 填上FB登入資訊
      • 填上FB版本(classic/new)
      • 填上IG登入資訊
    • 調整fanspages資料夾內目標爬蟲的粉專網址

/images/emoticon/emoticon41.gif 參考資源

  1. JSON 格式與 JavaScript 解析教學範例
  2. 用Math.random()取得亂數的技巧

免責聲明:文章技術僅抓取公開數據作爲研究,任何組織和個人不得以此技術盜取他人智慧財產、造成網站損害,否則一切后果由該組織或個人承擔。作者不承擔任何法律及連帶責任!


https://ithelp.ithome.com.tw/upload/images/20210720/20103256fSYXlTEtRN.jpg
在許多人的幫助下,本系列文章已出版成書,並添加了新的篇章與細節補充:

  • 加入更多實務經驗,用完整的開發流程讓讀者了解專案每個階段要注意的事項
  • 將爬蟲的步驟與技巧做更詳細的說明,讓讀者可以輕鬆入門
  • 調整專案架構
    • 優化爬蟲程式,以更廣的視角來擷取網頁資訊
    • 增加資料驗證、錯誤通知等功能,讓爬蟲執行遇到問題時可以第一時間通知使用者
    • 排程部分改用 node-schedule & pm2 的組合,讓讀者可以輕鬆管理專案程序並獲得更精確的 log 資訊

有興趣的朋友可以到天瓏書局選購,感謝大家的支持。
購書連結https://www.tenlong.com.tw/products/9789864348008


上一篇
【Day14】爬蟲執行時又又又崩潰了嗎?來點 try-catch 吧
下一篇
【Day16】不藏私,加上5行程式就能優化爬蟲的小技巧 & 學會爬蟲,之後呢?
系列文
行銷廣告、電商小編的武器,FB & IG 爬蟲專案從零開始30

1 則留言

0
飛飛
iT邦新手 4 級 ‧ 2020-09-30 16:04:16

你好用心寫文章,排版跟內容,好看又很豐富

居然收到大大的回覆,超級感動!

這麼多天來我一直怕自己的文章寫得不好沒有幫助到人,我之後會更認真的寫文的~
/images/emoticon/emoticon41.gif

snk iT邦新手 5 級 ‧ 2021-01-29 11:40:10 檢舉

寶寶出頭天感謝大大分享,您的文章非常仔細啊

snk能幫助到大家最重要~

我要留言

立即登入留言