AWS Lambdaに割り当てるメモリが少なすぎてスクレイピングに失敗していた
タイトルの通りです。
Lambda + Ruby2.5 + Mechanizeでのスクレイピングが50%ぐらいの確率で失敗していて、
原因がわからず彷徨っていたけどなんとなくメモリ増やしたら落ちなくなったのでメモ
ちなみに128MB -> 1024MBにしました
ユースケース的には、
毎日インスタの自社アカウントのフォロワー数を取得してslackに通知する、というプログラムを毎日定時にCloudWatchEventで動かしていたんですが,
(行儀がわるいのでInstagram Graph APIをつかえというのはナシで・・・)
class Fetcher INSTA_URL = 'https://www.instagram.com/****/?hl=ja'.freeze def initialize @agent = Mechanize.new @agent.user_agent_alias = 'Windows Mozilla' @insta_retry_count = 5 end # @abstract jsonldからもってくる # @return [String] def get_insta response = @agent.get(INSTA_URL) jsonld = response.at('script[type="application/ld+json"]').inner_text JSON.parse(jsonld, object_class: OpenStruct).mainEntityofPage.interactionStatistic.userInteractionCount.to_s rescue => e get_insta2 end # jsからもってくる # @abstract get_instaが失敗したときのためのフォールバック def get_insta2 response = @agent.get INSTA_URL js = response.search('script[type="text/javascript"]').find { |r| r.inner_text.include?('window._sharedData = ') }.inner_text matched = js.match(/"edge_followed_by":{"count":(\d+)}/) matched[1] rescue => e if @insta_retry_count >= 0 @insta_retry_count -= 1 get_insta else e.to_s end end end def lambda_handler(event:, context:) instance = Fetcher.new insta_count = instance.get_insta // 加工してslackに投げる処理 { statusCode: 200, body: JSON.generate('Hello!') } end
で undefined method
[]' for nil:NilClassを吐いていました
エラー箇所的には
matched[1]`のとこですね
元々のget_instaのみで(get_insta2とかいうふざけたメソッドなしで)実行していたときの失敗率と
get_insta2を追加してリトライを入れて実行したときの失敗率がほぼ変わらなかったし、
手元のdocker環境では失敗せず正常に動いていたので、環境特有のナニカ・・・うーん・・メモリかも・・・🤔と思って試しに
1024MB充ててみたら落ちなくなりましたとさ。おしまい。