概要
- ulrをクロールしたhtmlをS3に保存するlambda functionをSAMでdeployした
- ふつーにクロールすると1 url辺り5秒かかるとして1000url 5000秒。lambdaを使うと並列しょりできるので、所要時間はinvokeの時間+5秒なのでだいたい60秒ぐらいで終わる
- lambdaはruby
手順
AWS SAM インストール
https://docs.aws.amazon.com/ja_jp/serverless-application-model/latest/developerguide/serverless-sam-cli-install-mac.html
https://aws.amazon.com/jp/blogs/developer/announcing-ruby-build-support-for-aws-sam-cli/
brew tap aws/tap
brew install aws-sam-cli
ひな形作成
sam init --runtime ruby2.5 --name hello-ruby-sam
cd hello-ruby-sam
バケット作る
- SAM保存する & クロールしたhtmlを保存するバケットを作ります。(別々がいいですが、今回は手間を省略)
aws s3 mb s3://YOUR_NEW_BUCKET_NAME --region ap-northeast-1
コード書く
- urlのhtmlを取得してs3に保存するメソッドです。これがlambdaで実行されます。
- urlをハッシュにしてフォルダ名にして、その中にクロール日付(yyyymmdd.html)がついたファイルが作成されます。
- なのでページを取得するときはハッシュをキー
Digest::SHA256.hexdigest(url)
にして取得して下さい(urlをフォルダ名にしたいけどそれだとうまくいかないので) - そこら辺は説明省略
- なのでページを取得するときはハッシュをキー
- awsのキーとかはご自分のキーなどに適宜書き換えて下さい。
hello-ruby-sam/crawl_url/app.rb
require 'json'
require 'open-uri'
require 'aws-sdk-s3'
BUCKET_NAME = 'bucket-name'
BUCKET_REGION = 'bucket_region'
AWS_ACCESS_KEY = 'aws_access_key'
AWS_SECRET_KEY = 'aws_secret_key'
def lambda_handler(event:, context:)
url = event['url']
html = open(url) do |f|
f.read
end
s3 = Aws::S3::Resource.new(
region: BUCKET_REGION,
credentials: Aws::Credentials.new(AWS_ACCESS_KEY, AWS_SECRET_KEY)
)
obj = s3.bucket(BUCKET_NAME).object("#{Digest::SHA256.hexdigest(url)}/#{Time.now.strftime('%Y%m%d')}.html")
obj.put(body: html)
end
テンプレート
最後にテンプレートを編集。いらないところをバッサリと削ります。
hello-ruby-sam/template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
CrawlUrl
# More info about Globals: https://github.com/awslabs/serverless-application-model/blob/master/docs/globals.rst
Globals:
Function:
Timeout: 30
Resources:
CrawlUrlFunction:
Type: AWS::Serverless::Function # More info about Function Resource: https://github.com/awslabs/serverless-application-model/blob/master/versions/2016-10-31.md#awsserverlessfunction
Properties:
FunctionName: CrawlUrl
CodeUri: crawl_url/
Handler: app.lambda_handler
Runtime: ruby2.5
Outputs:
CrawlUrlFunction:
Description: "CrawlUrl Lambda Function ARN"
Value: !GetAtt CrawlUrlFunction.Arn
CrawlUrlFunctionIamRole:
Description: "Implicit IAM Role created for CrawlUrl function"
Value: !GetAtt CrawlUrlFunctionRole.Arn
デプロイ
デプロイします。
ついでにAWSのcloudformationを開いて見ているとごりごり動くのがわかるので楽しいです。
sam build
sam package \
--template-file template.yaml \
--output-template-file packaged.yaml \
--s3-bucket バケット名
sam deploy \
--template-file packaged.yaml \
--stack-name sam-app \
--capabilities CAPABILITY_IAM
- lambadaのファンクションが作られていれば成功です。
使う
- irbで試します。
-
aws-sdk
のgemが入った状態、invoke(url)
のurlの箇所に任意のurlを入れるて、S3にurlのhtmlが保存されます。
require 'aws-sdk'
BUCKET_NAME = 'bucket-name'
BUCKET_REGION = 'bucket_region'
AWS_ACCESS_KEY = 'aws_access_key'
AWS_SECRET_KEY = 'aws_secret_key'
def invoke(url)
client = Aws::Lambda::Client.new(region: 'ap-northeast-1', credentials: Aws::Credentials.new(AWS_ACCESS_KEY, AWS_SECRET_KEY))
req_payload = { url: url }
payload = JSON.generate(req_payload)
client.invoke({
function_name: 'CrawlUrl',
invocation_type: 'Event',
log_type: 'None',
payload: payload
})
end
invoke('https://ほしいurl')
以上
わからなかったこと
deploy時awsのキーを環境変数などで渡す方法がわからない。