AWS Amplify를 사용한 매우 쉬운 자동 스크래핑

13966 단어 aws
가장 중요한 데이터 중 너무 많은 것이 일시적입니다.

우리의 디지털 생활에는 실시간 업데이트 숫자로만 존재하는 많은 데이터 포인트가 있습니다. 그들은 잠시 번쩍인 다음 영원히 역사 속으로 사라집니다.

그러나 이러한 수치는 시간이라는 추가 차원을 추가하면 훨씬 더 많은 가치를 얻을 수 있습니다. 이것이 우리가 github star historiesnpm downloads 차트를 보는 것을 좋아하는 이유입니다. 다른 모든 추적을 저렴하고 쉽게 자동화할 수만 있다면 훨씬 더 많은 메가트렌드와 시장 점유율 정보를 손끝에서 사용할 수 있을 것입니다.

나는 이전에 scraping with GitHub Actions 에 대해 쓴 적이 있지만 git 및 GitHub Actions가 실제로 수행하도록 설계된 것이 아니기 때문에 확장 가능한 솔루션이 아닙니다.

오늘은 AWS Amplify로 데이터 스크래핑을 하는 방법을 공유하고자 합니다.



높은 수준의 아키텍처



우리의 데모 프로젝트는 Twitter 팔로워 수를 주기적으로 스크랩하고 나중에 분석하기 위해 데이터베이스에 저장할 것입니다. (물론 우리는 이것을 무엇이든 긁어내고 어디에나 저장하는 것으로 확장할 수 있습니다)

AWS Amplify CLI를 사용하여 몇 분 만에 이를 가동할 것입니다.



이것의 핵심은 우리가 작성할 AWS Lambda 함수입니다. Twitter에서 데이터를 가져온 다음 DynamoDB에 저장합니다. 스크랩을 트리거하는 두 가지 방법, 즉 CloudWatch의 이벤트 기반 트리거와 공개 API의 수동 트리거(API 게이트웨이를 통해 수행)가 있습니다.

설정



Amplify CLI installed and setup 이 있다고 가정하겠습니다.

증폭 프로젝트를 시작하고 리소스를 초기화합니다.

amplify init # choose all defaults

amplify add api # choose the options according to the below


이 명령 하나에서 실제로 예약된 CloudWatch Lambda 호출 및 해당 Lambda 함수와 연결된 DynamoDB 데이터베이스를 설정하도록 선택할 수 있습니다. 꽤 깔끔하죠?

# STEP ONE: Creating API

? Please select from one of the below mentioned services: REST
? Provide a friendly name for your resource to be used as a label for this category in the project: scrape
? Provide a path (e.g., /book/{isbn}): /scrape
? Choose a Lambda source Create a new Lambda function
? Provide an AWS Lambda function name: scrape
? Choose the runtime that you want to use: NodeJS
? Choose the function template that you want to use: CRUD function for DynamoDB (Integration with API Gateway)


# STEP TWO: Creating Database

? Choose a DynamoDB data source option Create a new DynamoDB table
? Please provide a friendly name for your resource that will be used to label this category in the project: scrapingd
b
? Please provide table name: scrapingdb

? What would you like to name this column: date
? Please choose the data type: string
? Would you like to add another column? No

? Please choose partition key for the table: date
? Do you want to add a sort key to your table? No

? Do you want to add global secondary indexes to your table? No
? Do you want to add a Lambda Trigger for your Table? No
Successfully added DynamoDb table locally


# STEP THREE: Schedule function invocation

Available advanced settings:
- Resource access permissions
- Scheduled recurring invocation # <---- we want this!!
- Lambda layers configuration

? Do you want to configure advanced settings? Yes
? Do you want to access other resources in this project from your Lambda function? Yes
? Select the category storage
Storage category has a resource called scrapingdb
? Select the operations you want to permit for scrapingdb create, read, update
? Do you want to invoke this function on a recurring schedule? Yes
? At which interval should the function be invoked: Hourly
? Enter the rate in hours: 6
? Do you want to configure Lambda layers for this function? No
? Do you want to edit the local lambda function now? No
Successfully added resource scrape locally.


개발하다



이제 방금 스캐폴드한 AWS Lambda 함수에서 작업할 수 있습니다. 나를 위해 일한 샘플 코드는 다음과 같습니다.

// amplify/backend/function/scrape/src/index.js
const fetch = require('node-fetch')
const cheerio = require('cheerio')
const util = require('util');
const AWS = require('aws-sdk')
AWS.config.update({ region: process.env.TABLE_REGION });
const dynamodb = new AWS.DynamoDB.DocumentClient();
const ddb = util.promisify(dynamodb.put);

let tableName = "scraperesults";
if(process.env.ENV && process.env.ENV !== "NONE") {
  tableName = tableName + '-' + process.env.ENV;
}
exports.handler = async (event, context) => {
  let data
  try {
    data = await (await fetch("https://twitter.com/swyx", {
      headers: {
        'User-Agent': "Googlebot/2.1 (+http://www.google.com/bot.html)"
      }
    })).text()
    const $ = cheerio.load(data)
    const count = Number($('.ProfileNav-item--followers .ProfileNav-value').attr('data-count'))
    const Item = {
      count,
      date: (new Date()).toString()
    }
    const data = await ddb({
      TableName: tableName,
      Item: Item
    })
    return {
      statusCode: 200,
      body: JSON.stringify({message: 'data saved!', Item})
    }
  } catch (error) {
    return {
      statusCode: 500,
      error
    }    
  }
};


AWS Lambda 함수의 새로운 종속성이므로 node-fetchcheerio를 설치해야 합니다.

테스트



함수를 개발할 때 빠른 반복 주기를 가질 수 있도록 배포하지 않고 로컬에서 테스트할 수 있습니다. Amplify는basic function mocking - GraphQL API(여기서는 사용하지 않음)를 모의 처리하지 않는 한 DynamoDB 부분을 모의 처리하지 않습니다.

amplify mock function <function_name> --event "src/event.json" # this file only matters if you are trying to simulate an event payload to your lambda function


배포



로컬에서 설정이 만족스러우면 클라우드로 푸시할 수 있습니다.

amplify push


그리고 배포되어 실행될 것입니다! Amplify 콘솔에서 Amplify 프로젝트를 볼 수 있습니다(터미널에서 amplify console를 실행하여 액세스할 수도 있음).



또한 개별 Lambda, API 게이트웨이, DynamoDB 및 CloudWatch 콘솔을 자세히 살펴보고 설정한 기본 서비스를 완전히 관찰할 수도 있습니다.



테이크아웃



작업을 완료하기 위해 맞춤형 서버리스 인프라를 가동하는 것이 그 어느 때보다 쉬워졌습니다!

이를 매우 안정적으로 구현하려면 HTML을 스크랩하는 대신 JS를 실행하거나 API를 핑하고 속도 제한 및 IP 차단의 경우 IP를 회전해야 할 수 있습니다. 더 배우고 싶다면 more web scraping notes on my GitHub cheatsheet이 있습니다.

좋은 웹페이지 즐겨찾기