AWS 덕분에 새 자전거를 갖게 된 방법!

저는 2019년에 첫 자전거를 구입했습니다. 전염병이 막 시작되었고 그 기간 동안 모든 팀 스포츠가 중단되었습니다. 자전거는 이미 몇 살이었고 수백 유로에 샀습니다. 나는 정말로 사이클링을 즐기기 시작했고 소규모 사이클링 팀에 합류했습니다.

2021년 여름, 나는 새 자전거를 찾기 시작했다. 내 오래된 것을 새 것으로 바꿀 때였습니다. 저는 Canyon Endurance CF SL 8에 관심을 갖게 되었지만 안타깝게도 항상 모두 매진되었습니다. 2021년 9월에 메일링 리스트에 가입했습니다. 모델 재고가 다시 있으면 이메일을 받게 됩니다.



몇 달 후 나는 왜 내가 이메일을 받지 못했는지 궁금해하기 시작했습니다. 유사한 자전거가 판매되는 것을 보았고 Reddit에서 약간의 조사를 한 후 알림 시스템이 제대로 작동하지 않는다는 것을 읽었습니다. 이메일은 아마도 작은 배지로 전송되었을 것이며 모든 Canyon Endurance CF SL 8이 다시 매진되기까지 몇 분도 걸리지 않았습니다.

다른 방법을 찾아야 할 때였습니다. 몇 초마다 사이트를 확인하는 데 사용할 수 있는 Distrill이라는 도구에 대해 읽었습니다. 무료 버전은 브라우저 플러그인과 함께 작동했습니다. 브라우저 없이 사용하려면 유료 요금제가 필요했습니다.

그래서 더 저렴하고 비슷한 것을 만들기로 결정했습니다.
나는 웹 페이지를 스크랩하고* 내 크기의 자전거가 여전히 사용할 수 없는지 확인하는 Lambda 함수를 개발하기로 결정했습니다. div 의 내용을 확인했습니다.



Python 모듈BeautifulSoup을 사용하여 웹 페이지를 스크랩하고 출시 예정 텍스트와 일치하는 항목을 찾았습니다.
텍스트가 변경되면 SNS를 사용하여 이메일로 알림을 받습니다.

""" Scrape Canyon site."""
import requests
import os

import boto3
from bs4 import BeautifulSoup

client = boto3.client("sns")

url = "https://www.canyon.com/xxx"

def lambda_handler(event, context):
    """Main."""
    page = requests.get(url)
    results = BeautifulSoup(page.content, "html.parser")

    items = []
    for div in results.findAll(
        "div", attrs={"class": "productConfiguration__availabilityMessage"}
    ):
        text = div.text
        items.append(text.strip())

    # size small is 4th of the list
    small_item = items[3]
    print("item: " + small_item)

    if "Soon" not in small_item:
        print("alert!")
        client.publish(
            TopicArn=os.environ["TOPIC"],
            Message="Time to buy a Canyon!",
            Subject="Time to buy a Canyon!",
        )


코드(및 실제로 전체 솔루션)는 정말 기본적입니다. 고급 통합이나 확인이 필요하지 않았습니다.
간단한 EventBridge 규칙을 사용하여 1분마다 Lambda를 트리거했습니다(잠을 자야 할 때는 제외!).

  Event:
    Type: AWS::Events::Rule
    Properties:
      Description: Trigger every minute
      Name: ScraperEvent
      # Run every minute when I don't sleep
      ScheduleExpression: cron(0/1 6-23 * * ? *)
      Targets:
        - Arn: !GetAtt Scraper.Arn #Lambda Arn
          Id: canyon-scraper
  LambdaPermission:
    Type: AWS::Lambda::Permission
    Properties:
      FunctionName: !GetAtt Scraper.Arn
      Action: lambda:InvokeFunction
      Principal: events.amazonaws.com
      SourceArn: !GetAtt Event.Arn


SNS는 알림을 보내는 데 사용되었습니다.

  Topic:
    Type: AWS::SNS::Topic
    Properties: 
      DisplayName: canyon-topic
      Subscription: 
        - Endpoint: [email protected]
          Protocol: email
      TopicName: canyon-topic


또한 기능을 최대한 빠르고 가볍게 만들기 위해 Lambda 레이어를 사용했습니다. Docker를 사용하여 레이어를 빌드하고 S3에 업로드했습니다.

$ docker run --rm \
--volume=$(pwd):/lambda-build \
-w=/lambda-build \
lambci/lambda:build-python3.8 \
pip install -r requirements.txt --target python

$ zip -vr python.zip python/

$ aws s3 cp python.zip s3://xxx-layers/python.zip


이 계층을 사용하도록 Lambda를 구성했습니다.

  Scraper:
    Type: AWS::Serverless::Function
    Properties:
      FunctionName: canyon-scraper
      CodeUri: src/
      Handler: lambda.lambda_handler
      Runtime: python3.8
      Role: !GetAtt ScraperRole.Arn
      Environment:
        Variables:
          TOPIC: !Ref Topic
      Layers:
        - !Ref libs
  libs:
    Type: AWS::Serverless::LayerVersion
    Properties:
      LayerName: python-lib
      Description: Dependencies for the canyon scraper
      ContentUri: s3://xxx-layers/python.zip
      CompatibleRuntimes:
        - python3.8


함수는 최소한의 메모리와 몇 초의 제한 시간으로 실행할 수 있을 만큼 빠릅니다.



이 기본 솔루션은 웹 사이트를 매분 모니터링했습니다. 1분보다 빠른 속도로 이어지는 Cron 표현식은 지원되지 않는다는 점에 유의해야 합니다. 더 빠른 솔루션이 필요한 경우 동료 커뮤니티 빌더this blog를 확인하십시오! 스크랩이 허용되고 서버가 플러딩되지 않는지 확인하세요!

이제 기다리기만 하면 한달만에 메일이 옵니다...



그리고 마음에 드는 자전거를 주문할 수 있었습니다! 그것은 나에게 큰 만족을 주었다. 많은 사람들과 마찬가지로 저도 새로운 AWS 기능, 멋진 통합 및 대규모 설정에 관심이 있지만 때로는 요구 사항을 충족하는 데 새롭고 멋진 기능이 필요하지 않을 수도 있습니다.

모든 코드를 사용할 수 있습니다here. 자유롭게 분기하고 필요에 맞게 조정하십시오.

*웹스크래핑은 규칙을 지킨다면 합법입니다.

좋은 웹페이지 즐겨찾기