概要
LambdaでRubyを使う際にNokogiriなどのGemを使おうとするとエラになってしまうので動かせるようにする
環境設定
※こちらはある程度されているものだと仮定します
ここらへんの記事を参考にcliツールなどを入れてください
https://qiita.com/itaya/items/a0f22addaab04456cae4
AWS側の準備
初期設定
プロジェクト名=好きな名前を指定してください
sam init --runtime ruby2.7 --name プロジェクト名
下記のように選択肢を迫られるので、1→1→nを選択します
Which template source would you like to use?
1 - AWS Quick Start Templates
2 - Custom Template Location
Choice: 1
Choose an AWS Quick Start application template
1 - Hello World Example
2 - Multi-step workflow
Template: 1
Based on your selections, the only Package type available is Zip.
We will proceed to selecting the Package type as Zip.
Based on your selections, the only dependency manager available is bundler.
We will proceed copying the template using bundler.
Would you like to enable X-Ray tracing on the function(s) in your application? [y/N]: n
そうするとディレクトリが一つ出来上がります。
コーディング
ディレクトリの中のコードを変更していきます
hello_world/
このディレクトリの中がLambdaの本体コードになるのでこちらを変更します
app.rb
# require 'httparty'
require 'json'
require 'nokogiri'
require 'uri'
require 'kconv'
require 'net/http'
def lambda_handler(event:, context:)
area = URI.encode_www_form_component('横浜')
keyword = URI.encode_www_form_component('居酒屋')
uri = URI.parse("https://r.gnavi.co.jp/area/jp/rs/?fwp=#{area}&date=&fw=#{keyword}")
request = Net::HTTP::Get.new(uri)
request["Authority"] = "r.gnavi.co.jp"
request["Accept"] = "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9"
request["Accept-Language"] = "ja"
request["Cache-Control"] = "max-age=0"
request["Cookie"] = "_td_global=2c7201bb-65d9-447f-8871-5c8aef70e6f0; _ra=1664900409701|e581f62a-e16f-4c02-97dc-b7ab203924e6; GU=e9f8c8528b624ea8cb1a55aadf705bd0; gt=GT139faa476002ac1e4ae520fpfeoIzpEqTDWQ1Rwc2xzV; ds=622474de466075942cc80e90a606c14bc6c474c7b09327535e48d587017aa4c0; gUser=03139faa476003ac1e4ae520L_I2dpFCb1q8eMMN-5-LmU; gcom=%7B%22login_type%22%3A1%2C%22guser_type%22%3A0%7D; _gid=GA1.3.151665219.1669743686; __gads=ID=61224817bcdcc5e2:T=1669743685:S=ALNI_MYQItLoO9f62eC3t0aHssBPge-pXQ; __gpi=UID=00000b86e8eecc21:T=1669743685:RT=1669743685:S=ALNI_MZ324J7fmISVdaU-A1IuoqdhZBTIQ; _ts_yjad=1669743686386; _fbp=fb.2.1669743686439.1159228644; _gcl_au=1.1.1560200380.1669743686; __pp_uid=INDH6tuKhtkFKURk66AXkbVTWOoJTybu; __lt__cid=c5331b8a-2798-4df1-9a8c-afb6b1af0c3c; __lt__sid=ab800c27-56441560; _dctagfq=1318:1670338799.0.0|1319:1670338799.0.0|1320:1670338799.0.0|1321:1670338799.0.0|1536:1670338799.0.0|1841:1670338799.0.0|1856:1670338799.0.0|1871:1670338799.0.0|1886:1670338799.0.0|1901:1670338799.0.0|1916:1670338799.0.0|1931:1670338799.0.0; ___o2u_o2id=0793b44a-526d-4f6f-bbfb-c923eb5be40f; rtosrch=gg7t002%3Dhttps%253A%252F%252Fr.gnavi.co.jp%252Farea%252Fjp%252Frs%252F%253Ffwp%253D%2525E6%2525A8%2525AA%2525E6%2525B5%25259C%2526date%253D%2526fw%253D%2525E3%252581%25259F%2525E3%252581%252593%2525E7%252584%2525BC%2525E3%252581%25258D%26a567203%3Dhttps%253A%252F%252Fr.gnavi.co.jp%252Farea%252Fjp%252Frs%252F%253Ffw%253D%2525E5%2525B1%252585%2525E9%252585%252592%2525E5%2525B1%25258B%2526fwp%253D%2525E6%2525A8%2525AA%2525E6%2525B5%25259C; GHistory=a567203%3A110%3A1669744542%2Cgg7t002%3A110%3A1669744522; ghistory_reserve=a567203%3A1669744542%2Cgg7t002%3A1669744522; __cribnotes_prm=__t_1669744547013_%7B%22uuid%22%3A%227a38921c-4d2e-4d30-bcb9-80d0686da7f0%22%7D; cto_bundle=sGp-Ll9kUDVaaHJYMHN3SkFtYyUyQkFmUTh2QWdka0pTQ0xqWlhHVFpETzB3ckh4dG1ya0J4NTB1Y0Z1V09mOUtMRDJWRlBKbDNSU2FTMWFDRXgyOFU4Q0l6UzAzYWFoWE9TMVd0WmVqOFZVcjBmQ3JHVHJyNkFodzhVcDlKTGdRYTBIWXNEdHdET3RzeENSc0Q0eDRGdUlwJTJGS3pWJTJGaXk1QW9sajk1ZUhJRHNaelpaYSUyRllHR0klMkZlNnhWWXIlMkJYTXB3eU00eUw; s_sess=%20sc_oncook%3D%3B%20sc_prop1%3Dr%3B%20cpnt_referer%3D%3B; _dc_gtm_UA-43329175-1=1; _td=639fb236-c732-4fb7-b246-0a6ed66c2a87; _ga_L9BHK8C28C=GS1.1.1669743685.1.1.1669744820.51.0.0; _ga=GA1.1.111137152.1669743686"
request["Sec-Ch-Ua"] = "\"Google Chrome\";v=\"105\", \"Not)A;Brand\";v=\"8\", \"Chromium\";v=\"105\""
request["Sec-Ch-Ua-Mobile"] = "?0"
request["Sec-Ch-Ua-Platform"] = "\"macOS\""
request["Sec-Fetch-Dest"] = "document"
request["Sec-Fetch-Mode"] = "navigate"
request["Sec-Fetch-Site"] = "same-origin"
request["Sec-Fetch-User"] = "?1"
request["Upgrade-Insecure-Requests"] = "1"
request["User-Agent"] = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/105.0.0.0 Safari/537.36"
req_options = {
use_ssl: uri.scheme == "https",
}
response = Net::HTTP.start(uri.hostname, uri.port, req_options) do |http|
http.request(request)
end
doc = Nokogiri::HTML.parse(response.body.toutf8, nil, 'utf-8')
results = doc.css('.style_restaurantNameWrap__wvXSR').map do |target|
target.text
end
{
statusCode: 200,
body: {
message: "Hello World!",
results: results
# location: response.body
}.to_json
}
end
上記のコードが何をしているかは
これとか参考にしてください。
簡単に言うとぐるなびのサイトから情報を取得してパースしてます。
ローカルでコードの実行
下記のコマンドでビルドして
sam build --use-container
下記のコマンドで実行すると
sam local invoke HelloWorldFunction --event events/event.json
こんな感じでAPIのレスポンスが返ってきてることがわかります。
Invoking app.lambda_handler (ruby2.7)
Skip pulling image and use local one: public.ecr.aws/sam/emulation-ruby2.7:rapid-1.66.0-x86_64.
Mounting /Users/itayayuuichirou/Documents/src/lambda/foo_scraper/.aws-sam/build/HelloWorldFunction as /var/task:ro,delegated inside runtime container
START RequestId: dd6e7259-a4a0-4e33-bcac-8ca32c52071f Version: $LATEST
END RequestId: dd6e7259-a4a0-4e33-bcac-8ca32c52071f
REPORT RequestId: dd6e7259-a4a0-4e33-bcac-8ca32c52071f Init Duration: 1.07 ms Duration: 2778.83 ms Billed Duration: 2779 ms Memory Size: 128 MB Max Memory Used: 128 MB
{"statusCode":200,"body":"{\"message\":\"Hello World!\",\"results\":[\"日吉 居酒屋 徳 0\",\"個室居酒屋 わら焼き直七(なおしち) 東戸塚店0\",\"居酒屋 まるは 0\",\"居酒屋さざん 中山駅前店0\",\"居酒屋さざん 日ノ出町駅前店0\",\"中華居酒屋 彩 関内0\",\"京個室 居酒屋 楓(かえで) 横浜駅前店0\",\"居酒屋 土間土間 横浜西口店0\",\"炭火居酒屋 もも 0\",\"居酒屋 土間土間 新横浜店0\",\"居酒屋 安ちゃん 0\",\"創作居酒屋 りき あざみ野店0\",\"〆蕎麦居酒屋 九 0\",\"中華居酒屋 ぼうず 0\",\"寿司居酒屋 七福 大口店0\",\"寿司居酒屋 太郎丸 上大岡店0\",\"寿司居酒屋 七福 戸塚店0\",\"和風居酒屋 末八 0\",\"寿司居酒屋 七福 上大岡店0\",\"九州居酒屋 エビス 市が尾店0\"]}"}%
デプロイ
では、このコードをデプロイしていきます。
sam package --output-template-file output.yaml --s3-bucket バケット名
sam deploy --template-file output.yaml --stack-name バケット名 --capabilities CAPABILITY_IAM
表示されるURLを叩くと
こんな感じでJSONが返ってくるかと思います。
以上!!
(細かい動きとかなんでそうなるのかは理解できていないので、勉強します...)