AWS Serverless

Serverless framework 使用 AWS Lambda 製作爬蟲到 AWS S3

常常我們要定期得到相關最新資訊,以往可能就要開一臺實體主機做 Cron Job, 這樣會造成伺服器的資源浪費。現在你有一個更經濟實惠的做法,那就是 Serverless。

常常我們要定期得到相關最新資訊,或是當公司把資料存到一個 A 地,需要定期把資料轉換搬移到 B 地做進一步的分析時。您就會想要做一個簡單的爬蟲去達到資料同步或是定期數據清理的角色。

但以往可能就要開一臺實體主機做 Cron Job, 這樣會造成伺服器的資源浪費。現在你有一個更經濟實惠的做法,那就是 Serverless。如果你不了解 Serverless 可以參考我們先前寫的文章

在這篇文章我們將會簡單的帶你製作一個非常簡單的爬蟲使用 AWS Lambda 去定期抓 “台灣上市公司每月營業收入彙總表“。

先到政府開放平台上的這個數據,複製 CSV 的連結,此 CSV 連結每個月為固定的 URL 。所以我們只要在每個月的數據更新時去重新抓這筆資料存到 AWS S3 我們就能夠不斷備份政府公開資訊。
CSV 連結:http://mopsfin.twse.com.tw/opendata/t187ap05_L.csv

這個 Tutorial 我們將會用 https://serverless.com/ Serverless Framework 做實作,也是目前最主流的 Serverless 框架。

安裝 Serverless

如果還沒有安裝 Serverless,輸入以下做安裝:

npm i -g serverless

撰寫程式以及檔案

安裝完後,此教學將會使用 NodeJS 所以用 Serverless command 創立一個新專案使用 NodeJS 的樣板

$ serverless create --template aws-nodejs

你會看到 serverless.yaml 此檔案,這是 Serverless 這個 framework 中最重要的檔案,他可以幫助你直接設置好所有雲端供應商的設定。只需要把資料設定完之後上傳你所有 CloudFromation, CloudWatch, S3, AWS Glue 等設定。

接下來去 serverless.yml 這個檔案如下:

service: tw-ipo-revenue

custom:
  outputBucket: data-driven-blog # 將會把資料最後放到這個 S3 bucket 中

provider:
  name: aws
  runtime: nodejs10.x
  region: ap-southeast-1
  iamRoleStatements:
    - Effect: Allow
      Action:
        - s3:PutObject
        - s3:PutObjectAcl
      Resource: "arn:aws:s3:::${self:custom.outputBucket}/*"

# 你要 trigger 的 function 寫在這粒
functions:
  crawl:
    handler: handler.crawl
    environment:
      OUTPUT_BUCKET: ${self:custom.outputBucket}
    events:
      # cron job 設定多久多少時間要 trigger 這個 function
      - schedule: cron(0 8 3 * ? *)

由於我們需要有權限可以上傳到 AWS S3, CloudFormation, 以及 Lambda 所以您需要創立一個新的使用者在 AWS IAM 中(請參考這篇文章創立新使用者

events 中可以看到 Cron Job 設定為 cron(0 8 3 * ? *) 您可以自己修改 Cron Job 的時程參考這個連結

接下來我們要創立一個 hander.js 這邊設定我們的爬蟲。

'use strict';
const axios = require('axios');
const AWS = require('aws-sdk');
const s3 = new AWS.S3();

const bucketName = process.env.OUTPUT_BUCKET
const bucketKeyPrefix = "tw_ipo_company_revenue/"

module.exports.crawl = async (event, context, callback) => {
  return axios.get('http://mopsfin.twse.com.tw/opendata/t187ap05_L.csv')
    .then(function(res) {
      return new Promise ((resolve, reject) => {
        const params = {Bucket: bucketName, Key: bucketKeyPrefix + Date.now() + '.csv', Body: res.data};
        s3.putObject(params, function(err, data) {
          if (err) {
            reject(err)    
          } else {
            resolve(data);
          }
        });
      });
    })
    .then((data) => {
      callback(null, { success: true, msg: data });
    })
    .catch((error) => {
      callback(error, { success: false });
    });
};

同時要設定好 npm packages

# init npm
$ npm init
# install required packages
$ npm i --save aws-sdk axios

執行 deploy

最終我們的 file 架構長得像這樣

接下來就是 deploy!

$ serverless deploy

Serverless: Packaging service...
Serverless: Excluding development dependencies...
Serverless: Safeguards Processing...
Serverless: Safeguards Results:

   Summary --------------------------------------------------

   passed - no-secret-env-vars
   passed - allowed-regions
   passed - framework-version
   passed - no-unsafe-wildcard-iam-permissions
   passed - allowed-runtimes
   warned - require-cfn-role
   passed - allowed-stages

   Details --------------------------------------------------

   1) Warned - no cfnRole set
      details: http://slss.io/sg-require-cfn-role
      Require the cfnRole option, which specifies a particular role for CloudFormation to assume while deploying.


Serverless: Safeguards Summary: 6 passed, 1 warnings, 0 errors
Serverless: Creating Stack...
Serverless: Checking Stack create progress...
.....
Serverless: Stack create finished...
Serverless: Uploading CloudFormation file to S3...
Serverless: Uploading artifacts...
Serverless: Uploading service tw-ipo-revenue.zip file to S3 (7.79 MB)...
Serverless: Validating template...
Serverless: Updating Stack...
Serverless: Checking Stack update progress...
...........................
Serverless: Stack update finished...
Service Information
service: tw-ipo-revenue
stage: dev
region: ap-southeast-1
stack: tw-ipo-revenue-dev
resources: 9
api keys:
  None
endpoints:
  None
functions:
  crawl: tw-ipo-revenue-dev-crawl
layers:
  None

....

接下來到 AWS 的 Lambda console:

點入內容裡面可以看到 Serverless 自動幫我們把 CloudWatch, S3, Lambda 接起來了!

接下來觸發一次執行

到 S3 的畫面ㄝ你可以看到多了一個 folder 叫做 tw_ipo_company_revenue 資料夾裡面就存放那個資料!

刪除 Serverless

如果要把這個 Serverless 刪掉也很簡單,輸入:

$ serverless remove

製作爬蟲是不是變得更簡單而且經濟實惠了呢? Serverless 的最大優勢就是不需要維護 backend 而且他只有在執行的期間才收費!下次可以試試看使用 Serverless 製作您的爬蟲或是簡易的 ETL!

Processing…
Success! You're on the list.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: