네트워크 공부 & 실습/네트워크 실습

[Network] AWS 탈퇴 및 Blog 스크랩 자동화 스크립트 셋팅하기 (to 라즈베리파이)

강_토발즈 2025. 5. 28. 23:31

 

 

 

 

이 세상에 간단한 자동화 기능을 한다고 해서 한달에 1만원 가까이 가져가는 서비스가 뭐냐? 바로 AWS EC2 이다.

물론 기본 리소스와 보안, 기타 등등의 서비스를 모두 제공하는 것을 내가 쓰지 못하고 있는 것도 있지만, 그다지 큰 리소스도 사용하지 않고 1일 1회의 자동화를 실행하는 블로그 스크랩 기능을 라즈베이 파이로 옮기고, AWS 를 탈퇴하도록 하자!

 

 

 

1. AWS 로그인 하기 

 

.

 

비밀번호를 맞게 입력한 것 같은데 틀린다고 나온다. 
AWS 는 생각보다 비밀번호 재 설정이 쉽다. 저 보안문자만 통과하면 가입한 이메일로 새로운 비밀번호를 설정할 수 있는 링크를 보내준다. 노안이 온건지 저 글자들이 잘 안보여서 2번 실패했지만, 3번째에 성공해서 비밀번호를 변경해서 로그인 할 수 있었다.

 

 

 

2. 오랜만에 둘러보기

오랜만에 AWS 가 잘 살고 있나 보려는 찰나, 바로 사용 금액이 보인다. 니가 뭐 했다고 벌써 6달러를 청구해??

이게 왜 니돈이야

 

 

 

EC2는 3달이 좀 넘게 켜있었다. 이제 오늘부로 영원히 재워줄게...

EC2 에 있는 자동화 스크립트는, 이전 포스팅이나 로컬에 남겨져 있기 때문에 미련없이 보내주도록 한다.

 

 

3. 헤어지기

 

우리집 주소랑, 내 전화번호랑, 결제 카드 정보까지 가지고 있었구나...

하지만 이제 미련없이 계정 해지 버튼을 눌러준다.

 

 

 

탈퇴 시 피드백을 달라고한다. 4개중에 2개만 채운다. 난 탈퇴할 때 반만 가져가...

 

 

 

생각보다 깔끔하게 헤어졌다. 하지만 여태 사용한 비용은 청구할 것 같다.

이후에도 혹시 요금이 나온다면, 다시 로그인하여 정산이 안된 것을 확인해야 한다.

 

 

4.필요한 파이썬 라이브러리 설치

 

 

이전 자동화 포스팅 내용을 참고하여 필요한 라이브러리를 설치 한다.

 

https://cs-study1.tistory.com/72

 

[블로그 포스팅 Auto Push] 로컬 PC

블로그에 포스팅 된 내용을 자동으로 스크랩 하여 특정 저장소에 [포스팅제목].md 파일을 생성하도록 하고,이 생성된 파일이 Github에 commit& push 되도록 셋팅 하고자 한다. 작업순서 1. 블로그의

cs-study1.tistory.com

 

파이썬 가상화 환경을 활성화 하고, 필요한 라이브러리를 설치해준다.

source /home/kang/venv/bin/activate


pip install requests beautifulsoup4 gitpython watchdog

 

pip list 로 볼 수 있다

 

필요한 라이브러리들이 제대로 설치 되었다.

 

 

 

5. 자동화 스크랩 파일 옮기기

 

이전 포스팅에 작성한 자동화 스크립트들을 vi 편집기를 이용해서 옮겨준다.

 

import os
import time
import git
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler

class ChangeHandler(FileSystemEventHandler):
    def __init__(self):
        super().__init__()
        self.is_committing = False  # 커밋 중인지 여부를 나타내는 플래그

    def on_created(self, event):
        if event.is_directory or self.is_committing:
            return

        # 무시할 파일 목록
        ignored_files = [
            'COMMIT_EDITMSG',
            'main.lock',
            'HEAD.lock',
            'index.lock'
        ]

        # Git 관련 임시 파일 무시
        if any(event.src_path.endswith(ext) for ext in ['.lock', '.tmp']):
            return

        # 무시 목록에 포함되어 있는지 확인
        if os.path.basename(event.src_path) in ignored_files:
            return

        repo_path = '/home/kang/Documents/blog_scrap'  # Git 저정소가 연결된 로컬 저장소
        repo = git.Repo(repo_path)

        # 커밋 중 플래그 설정
        self.is_committing = True

        try:
            # 변경 사항 추가 및 커밋
            repo.git.add(A=True)
            commit_message = f"Added: {os.path.basename(event.src_path)}"
            repo.index.commit(commit_message)
            print(f"Committed: {commit_message}")

            # 푸시 (upstream 설정 포함)
            repo.git.push('origin', 'main')  # 원격 브랜치 설정 포함
            print(f"Pushed: {commit_message}")

        except Exception as e:
            print(f"Error occurred: {e}")
        finally:
            # 커밋이 끝난 후 대기
            time.sleep(600)  # 10분 대기
            self.is_committing = False

if __name__ == "__main__":
    path = '/home/kang/Documents/blog_scrap'  # 감지할 폴더
    event_handler = ChangeHandler()
    observer = Observer()
    observer.schedule(event_handler, path, recursive=True)

    observer.start()
    print(f"Watching for changes in {path}...")

    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()

 

import requests
from bs4 import BeautifulSoup
import os

def scrape_blog_to_md(url, filename):
    response = requests.get(url)
    if response.status_code != 200:
        print(f"블로그 페이지를 가져오는 데 실패했습니다. 상태 코드: {response.status_code}")
        return

    soup = BeautifulSoup(response.content, 'html.parser')
    title = soup.find('title').get_text()
    content = soup.find('div', class_='tt_article_useless_p_margin contents_style')

    if content is None:
        print("기사 내용을 찾을 수 없습니다.")
        return

    filepath = f"/home/kang/Documents/blog_scrap/article/{filename}"
    with open(filepath, 'w', encoding='utf-8') as f:
        f.write(f"# {title}\n\n")
        f.write(content.get_text(strip=True, separator='\n'))

def get_blog_number():
    num_file_path = "blog_number.txt"

    if not os.path.exists(num_file_path):
        with open(num_file_path, 'w') as f:
            f.write("1")
        return 1

    with open(num_file_path, 'r') as f:
        current_number = int(f.read().strip())

    return current_number

def save_blog_number(number):
    with open("blog_number.txt", 'w') as f:
        f.write(str(number))

if __name__ == "__main__":
    # 블로그 번호 가져오기
    blog_no = get_blog_number()
    url = f"https://cs-study1.tistory.com/{blog_no}"
    filename = f"blog_post_{blog_no}.md"

    # 스크랩 실행
    scrape_blog_to_md(url, filename)
    print(f"{filename}에 블로그 내용이 저장되었습니다.")

    # 블로그 번호 증가
    blog_no += 1
    save_blog_number(blog_no)

    print(f"다음 블로그 번호: {blog_no}.")

 

 

마지막으로, git 저장소와 /home/kang/Documents/blog_scrap 디럭터리를 연결해준다.
연결하고 기존의 레포지토리를 pull 해온다.

 

# 내 경로에서
git init

git remote add origin https://github.com/sinwoongkang1/tistory_scapper.git

 

 

6. 실행 해보기

실행 순서는 changeHandler 로 변경감지를 켠 상태에서 scrape_blog 가 블로그를 스크랩 해오면, 변경을 감지해서 커밋하는 설계이다.

 

 

변경감지 시작
스크랩 시작
커밋 에러

 

스크래핑이 진행되고, 감시 스크립트가 변경을 감지하고 push 를 진행했다. 첫 push 의 경우 git 의 ID 와 Password 를 입력해야 하는데, Github 는 2021년 8월 이후로 패스워드 인증을 막고, Personal Access Token 으로 인증을 대체해야 한다. 

 

하지만 매번 토큰을 입력하는 것은, 자동화의 원칙에 위배되기 때문에 토큰을 저장하는 방식을 이요하도록 한다. ( 캐시 방식으로 메모리에 일정 기간만 저장하는 방식도 있지만, 일단은 영구 저장 방식을 이용한다.)

 

git config --global credential.helper store

# 이후 토큰 넘버 입력

 

토큰을 입력하니 push 완료

 

 

토큰을 입력 후 push 가 성공하자 이후 14번 15번 째 내용은 따로 토큰 번호 입력 없이 자동으로  commit & push  되었다.

 

이제 crontab 에 자동화를 등록한다.

먼저 변경감지하는 changeHandler.py 를 월~금 20시 30분에 동작시키고 20시 31분에 scrape_bog.py를 동작시킨다. 그러면 커밋 푸쉬가 되고, 좀 여유를 주고 20시 35분에 changeHandler.py 를 종료하는 시나리오대로 작성해준다.

 

crontab -e

# 월~금 20:30에 감지 시작
30 20 * * 1-5 /home/kang/start_change_handler.sh

# 월~금 20:31에 스크랩 실행
31 20 * * 1-5 /home/kang/venv/bin/python /home/kang/Documents/blog_scrap/scrape_bog.py

# 월~금 20:35에 감지 종료
35 20 * * 1-5 pkill -f changeHandler.py

 

crontab -l 로 확인한 모습

 

 

7. 마무리

 

어제 진행하였던 시스템 정보 수집 및 DB 저장의 경우 라즈베리파이 정보까지 분리 저장하는 것으로 확장되어 시간이 오래 걸렸지만, 오늘 진행한 자동화 옮기기는 경로와 인증 문제만 해결하니 손 쉽게 진행되었다. 하지만 뭔가 항상 찜찜하게 삥을 뜯어가던 AWS 와 이별하였기 때문에, 상당히 개운하게 하루를 마무리 할 수 있게 되었다. 마지막으로 어제 설정한 라즈베리 파이에 대한 시스템 수집 정보가 NAS 의 MariaDB 에 1시간 마다 잘 저장되고 있는지 확인 한 후 오늘의 공부를 마무리 한다.