반응형

서론

텍스트 파일 내에서 특정 조건에 맞는 내용을 검색하고 필터링하는 기능은 시스템 관리, 데이터 분석, 로그 분석 등 다양한 분야에서 필요한 경우가 많습니다. 예를 들어, 시스템 로그에서 오류 메시지를 찾거나 특정 사용자의 활동을 추적하는 데 유용합니다. 파이썬의 강력한 정규 표현식 지원 기능을 활용하면 이러한 작업을 효율적으로 수행할 수 있습니다. 이 글에서는 파이썬을 이용해 텍스트 파일 내에서 정규 표현식을 활용한 검색 및 필터링 방법을 구체적으로 설명합니다. 이를 통해 사용자는 다양한 상황에서 필요한 데이터를 빠르게 추출하고 분석할 수 있게 됩니다.

핵심 개념

정규 표현식 기초

정규 표현식은 특정 패턴을 검색하는 데 사용되는 실제로 써먹기 좋은 방법입니다. 몇 가지 기본 메타 문자를 살펴보겠습니다:
- . : 임의의 문자를 나타냅니다.
- * : 선행 또는 후행 0개 이상 반복을 나타냅니다.
- + : 선행 또는 후행 1개 이상 반복을 나타냅니다.
- ? : 선행 0개 또는 1개 반복을 나타냅니다.
- [] : 특정 문자 집합 내의 문자를 나타냅니다.
- \d : 숫자 (0-9)를 나타냅니다.
- \w : 알파벳과 숫자 (문자 및 밑줄)를 나타냅니다.
- \s : 공백 문자를 나타냅니다.

파이썬의 re 모듈 사용법

파이썬에서 정규 표현식을 사용하기 위해 re 모듈을 활용합니다. 주요 함수들은 다음과 같습니다:
- re.search(pattern, string): 문자열 내에서 패턴의 첫 번째 매치를 찾습니다.
- re.findall(pattern, string): 문자열 내에서 모든 매치를 리스트로 반환합니다.
- re.compile(pattern): 정규 표현식 패턴을 컴파일하여 효율적으로 재사용할 수 있습니다.

사용 전 주의할 점

이 글의 예제는 본인이 관리하는 사이트, 테스트 서버, 사내 시스템처럼 자동화 사용이 허용된 환경을 기준으로 설명합니다.

실제 서비스에 적용할 때는 해당 사이트의 이용 약관을 먼저 확인해야 합니다. 캡차, 2단계 인증, 보안 확인 절차를 우회하는 용도로 사용하면 안 됩니다.

아이디와 비밀번호는 코드에 직접 적기보다 환경 변수나 별도 설정 파일로 관리하는 편이 안전합니다.

코드 구현

예제 텍스트 파일 생성 및 준비

텍스트 파일을 생성하거나 사용합니다. 실제 작업에서는 해당 파일의 경로를 적절히 설정해야 합니다. 예제 파일은 다음과 같은 내용을 포함합니다:

[SYSTEM LOG] 2023-10-27 10:00:01 [User: admin] Login Success
[SYSTEM LOG] 2023-10-27 10:05:23 [User: john_doe@여기에_URL_입력] Action: Upload
[SYSTEM LOG] 2023-10-27 10:10:45 [User: jane.doe] Action: Download
[SYSTEM LOG] 2023-10-27 10:15:12 [User: support@company.com] Status: ERROR
[SYSTEM LOG] 2023-10-27 10:20:00 [User: test@user] Phone: +82-10-1234-5678
[SYSTEM LOG] 2023-10-27 10:25:00 [User: admin] Login Failed
import re
import os

# 파일 경로 변수 설정
TARGET_FILE_PATH = "target.txt"  # 실제 파일 경로로 변경 필요

# 검색할 패턴 정의
PATTERNS = {
    "email_pattern": r"[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}",
    "error_keyword": r"ERROR",
    "phone_pattern": r"\+?[0-9]{2,3}\s?-?\s?[0-9]{3,4}\s?-?\s?[0-9]{4}",
}

def create_sample_file():
    """
    예제를 위해 sample 텍스트 파일을 생성하는 함수
    실제 작업을 위해서는 이 함수 대신 실제 파일을 사용하는 경로를 설정
    """
    sample_content = """
    [SYSTEM LOG] 2023-10-27 10:00:01 [User: admin] Login Success
    [SYSTEM LOG] 2023-10-27 10:05:23 [User: john_doe@여기에_URL_입력] Action: Upload
    [SYSTEM LOG] 2023-10-27 10:10:45 [User: jane.doe] Action: Download
    [SYSTEM LOG] 2023-10-27 10:15:12 [User: support@company.com] Status: ERROR
    [SYSTEM LOG] 2023-10-27 10:20:00 [User: test@user] Phone: +82-10-1234-5678
    [SYSTEM LOG] 2023-10-27 10:25:00 [User: admin] Login Failed
    """

    if not os.path.exists(TARGET_FILE_PATH):
        with open(TARGET_FILE_PATH, 'w', encoding='utf-8') as f:
            f.write(sample_content)
            print(f"예제 파일 [{TARGET_FILE_PATH}] 이(가) 생성되었습니다.")

create_sample_file()

정규 표현식을 활용한 검색 코드 예제

정규 표현식을 사용하여 파일 내에서 특정 패턴을 검색합니다.

def filter_text_file(file_path, regex_pattern):
    """
    지정된 정규 표현식으로 텍스트 파일 필터링
    매칭된 라인만 추출
    """
    matched_lines = []
    try:
        with open(file_path, 'r', encoding='utf-8') as f:
            for line in f:
                if re.search(regex_pattern, line):
                    matched_lines.append(line.strip())
    except FileNotFoundError:
        print(f"오류: 파일 [{file_path}] 을(를) 찾을 수 없습니다.")
        return matched_lines
    except PermissionError:
        print(f"오류: 파일 [{file_path}] 에 접근 권한이 없습니다.")
        return matched_lines
    except re.error as e:
        print(f"오류: 정규 표현식 패턴 오류 - {e}")
        return matched_lines

    return matched_lines

검색 결과 필터링 및 출력 코드 예제

필터링된 결과를 콘솔에 출력합니다.

def run_analysis():
    """
    메인 분석 루틴
    """
    print("\n--- 필터링 결과 출력 ---")

    # 각 패턴별로 검색 결과 출력
    for pattern_name, pattern in PATTERNS.items():
        print(f"\n1. 패턴명: {pattern_name}")
        print(f"   검색 내용: {pattern}")
        results = filter_text_file(TARGET_FILE_PATH, pattern)
        if results:
            print(f"   일치한 라인 ({len(results)}개):")
            for line in results:
                print(f"   > {line}")
        else:
            print("   일치한 라인 없음")

if __name__ == "__main__":
    try:
        run_analysis()
    except Exception as general_error:
        print(f"예상치 못한 오류 발생: {general_error}")

실행 방법

  1. 코드 저장: 해당 코드를 search_text.py 파일로 저장합니다.
  2. 파이썬 설치 확인: 파이썬이 설치되어 있는지 확인합니다.
  3. 코드 실행: 터미널 또는 명령 프롬프트에서 아래 명령어를 실행합니다.
    python search_text.py
  4. 예제 파일 확인: 스크립트가 실행되면 예제 파일이 생성되거나 기존 target.txt 파일을 분석합니다. 결과는 콘솔에 출력됩니다.

예상 실행 결과

예제 파일 [target.txt] 이(가) 생성되었습니다.

--- 필터링 결과 출력 ---

1. 패턴명: email_pattern
   검색 내용: [a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}
   일치한 라인 (2개):
   > [SYSTEM LOG] 2023-10-27 10:05:23 [User: john_doe@여기에_URL_입력] Action: Upload
   > [SYSTEM LOG] 2023-10-27 10:15:12 [User: support@company.com] Status: ERROR

1. 패턴명: error_keyword
   검색 내용: ERROR
   일치한 라인 (1개):
   > [SYSTEM LOG] 2023-10-27 10:15:12 [User: support@company.com] Status: ERROR

1. 패턴명: phone_pattern
   검색 내용: \+?[0-9]{2,3}\s?-?\s?[0-9]{3,4}\s?-?\s?[0-9]{4}
   일치한 라인 (1개):
   > [SYSTEM LOG] 2023-10-27 10:20:00 [User: test@user] Phone: +82-10-1234-5678

코드 설명

  • create_sample_file(): 예제 텍스트 파일을 생성하는 함수입니다. 실제 작업에서는 이 부분을 실제 파일 경로로 대체해야 합니다.
  • filter_text_file(file_path, regex_pattern): 지정된 정규 표현식 패턴으로 텍스트 파일을 필터링합니다. 매칭된 라인만 리스트에 저장하여 반환합니다.
  • run_analysis(): 메인 루틴으로, 각 패턴에 대해 파일을 검색하고 필터링된 결과를 콘솔에 출력합니다.

사용자가 반드시 수정해야 하는 부분

  • TARGET_FILE_PATH: 분석할 실제 텍스트 파일의 경로를 설정해야 합니다. 예를 들어, "path/to/your/target.txt"로 변경하세요.
  • PATTERNS: 필요한 검색 패턴을 추가하거나 수정할 수 있습니다. 예를 들어, 새로운 이메일 패턴을 추가하거나 특정 키워드를 검색하도록 수정할 수 있습니다.

실행 전 확인 사항

  • 파이썬 설치: 파이썬이 시스템에 설치되어 있는지 확인하세요 (python --version 명령어 실행).
  • 파일 접근 권한: 코드가 실행되는 디렉토리에서 파일을 읽고 쓸 수 있는 권한이 있는지 확인하세요.
  • 파일 존재 여부: 예제 파일이 생성되거나, 실제 분석할 파일이 존재하는지 확인하세요.

자주 발생하는 오류와 해결 방법

  1. 파일 경로 오류
  2. 원인: TARGET_FILE_PATH 경로가 올바르지 않거나 파일이 존재하지 않을 때 발생합니다.
  3. TARGET_FILE_PATH = os.path.abspath("path/to/your/target.txt")
  4. 정규 표현식 오류 (re.error)
  5. 원인: 패턴 문자열에 닫는 괄호 ] 또는 중괄호 } 가 누락되어 있을 때 발생합니다.
  6. escaped_pattern = re.escape(your_pattern)
  7. 인코딩 문제
  8. 원인: 파일 인코딩이 환경 설정과 맞지 않을 때 발생합니다.
  9. 해결 방법: open() 함수의 encoding 매개변수를 적절히 설정하세요 (예: utf-8 또는 cp949).
with open(file_path, 'r', encoding='utf-8') as f:

마무리

이 글을 통해 텍스트 파일 내에서 특정 조건에 맞는 내용을 검색하고 필터링하는 방법을 배웠습니다. 정규 표현식을 활용하면 텍스트 처리가 훨씬 효율적이고 정확해집니다. 추가 학습을 위해 정규 표현식 가이드나 파이썬 re 모듈 공식 문서를 참조해보세요. 다음 단계로는 다양한 정규 표현식 패턴을 추가하거나 다른 파일 형식 (예: CSV, 엑셀)에 대한 텍스트 검색 기능을 확장해볼 수 있습니다. 이러한 기술은 데이터 분석, 시스템 관리 등 다양한 업무에서 매우 유용하게 활용될 수 있습니다.

실제로 테스트할 때 먼저 확인한 부분

파이썬 자동화 코드는 코드 내용만큼 실행 위치와 파일 경로가 중요합니다.

제가 테스트할 때도 코드가 틀린 줄 알았는데, 실제로는 터미널을 다른 폴더에서 실행해서 파일을 찾지 못한 경우가 많았습니다.

따라서 예제를 실행하기 전에 현재 터미널 위치, 파일명, 필요한 라이브러리 설치 여부를 먼저 확인하는 것이 좋습니다.

테스트 환경

이 글은 아래와 같은 환경을 기준으로 설명합니다.

  • Windows 11
  • Python 3.11
  • VS Code 또는 기본 터미널
  • 필요한 라이브러리 설치 완료 상태

Mac이나 Linux에서도 비슷하게 실행할 수 있지만, 경로 표기와 터미널 명령어는 환경에 맞게 조금 바꿔야 합니다.

제가 테스트하면서 자주 막혔던 부분

파이썬 예제에서 자주 막히는 부분은 라이브러리 설치 위치와 실행 위치였습니다.

분명히 pip install을 했는데도 모듈을 찾지 못한다면, 현재 실행 중인 Python과 pip가 같은 환경을 보고 있는지 확인해야 합니다.

또 파일을 다루는 예제라면 터미널을 어느 폴더에서 실행했는지에 따라 파일을 찾지 못하는 문제가 자주 생깁니다.

반응형
반응형

이 자동화가 필요한 상황

업무 환경에서 반복적으로 발생하는 이미지 분류 작업은 시간과 리소스를 많이 소모하며, 오류 발생 가능성을 항상 내포하고 있습니다. 예를 들어, 매일 특정 웹사이트에서 이미지 데이터를 수집하고, 이를 자동으로 분류해야 하는 상황을 상상해보세요. 수동으로 이미지를 하나씩 분류하려면 상당한 시간이 걸리고, 인간의 오류 가능성도 배제할 수 없습니다. 이러한 문제를 해결하기 위해 YOLOv8 기반 화면 캡처 및 자동 이미지 분류 시스템을 구축함으로써 업무 효율성을 크게 향상시킬 수 있습니다. 이 시스템은 화면에서 자동으로 이미지를 캡처하고, 고도의 정확도를 자랑하는 YOLOv8 모델을 활용하여 이미지를 즉시 분류합니다. 분류 결과는 Google Sheets와 연동하여 데이터 관리와 추적이 용이해집니다.

전체 흐름 먼저 이해하기

  1. 화면 캡처: PyAutoGUI를 사용하여 필요한 이미지를 캡처합니다.
  2. 이미지 분류: YOLOv8 모델을 사용하여 캡처된 이미지를 분류합니다.
  3. 결과 저장 및 웹 서비스 제공: 분류 결과를 Google Sheets에 저장하고, Flask 웹 서비스를 통해 외부에서도 접근 가능하도록 합니다.

준비해야 할 것

설치해야 할 라이브러리

pip install ultralytics opencv-python-headless pyautogui flask google-api-python-client pandas

필요한 파일 및 설정

  • YOLOv8 모델 파일: yolov8n.pt 또는 원하는 성능에 맞는 모델 파일 다운로드
  • Google Sheets API 인증 파일 (service_account.json): Google Cloud Console에서 생성한 서비스 계정 JSON 파일
  • Google Sheets ID와 범위: Google Sheets에서 설정한 시트 ID와 데이터 저장 범위 (예: Classifications!A1:B100)

초보자가 놓치기 쉬운 준비사항

  • Google Sheets 설정: service_account.json 파일의 이메일 주소와 Google Sheets 문서 공유 설정이 정확히 일치해야 합니다.
  • 보안 주의: service_account.json 파일은 보안적으로 안전한 장소에 보관해야 합니다.

핵심 코드 구현

화면 캡처 및 이미지 분류 기능

  import cv2
import numpy as np
import pyautogui
import requests
from flask import Flask, jsonify, request
from ultralytics import DetectionPipeline  # YOLOv8 모델 로드
import os
from google.oauth2.credentials import Credentials
from googleapiclient.discovery import build

# Flask 앱 생성
app = Flask(__name__)

# YOLOv8 모델 경로 설정 및 로드
MODEL_PATH = "yolov8n.pt"  # 모델 경로 지정 (예: yolov8n.pt)
try:
    model = DetectionPipeline(MODEL_PATH)
except Exception as e:
    print(f"모델 로드 실패: {e}")
    model = None

# Google Sheets 서비스 설정
GOOGLE_SHEET_SERVICE_ACCOUNT_FILE = "service_account.json"
SHEET_ID = "여기에-구글-시트-ID-입력"  # 구글 시트 ID 입력
SHEET_RANGE = "Classifications!A1:B100"  # 데이터 저장 범위

class GoogleSheetsAPI:
    def __init__(self):
        try:
            if os.path.exists(GOOGLE_SHEET_SERVICE_ACCOUNT_FILE):
                credentials = Credentials.from_service_account_file(
                    GOOGLE_SHEET_SERVICE_ACCOUNT_FILE,
                    scopes=["https://www.googleapis.com/auth/spreadsheets"]
                )
                self.sheet = build("sheets", "v4", credentials=credentials)
                self.is_ready = True
            else:
                self.is_ready = False
                print("Google Sheets 서비스 계정 파일이 존재하지 않습니다.")
        except Exception as e:
            self.is_ready = False
            print(f"Google Sheets 인증 실패: {e}")

    def update_sheet(self, data):
        """
        Google Sheets에 분류 결과를 저장합니다.
        """
        if not self.is_ready:
            return {"status": "error", "message": "Google Sheets 연결 불가"}

        try:
            value = [data]
            body = {
                "valueInputOption": "USER_ENTERED",
                "resources": [
                    {
                        "sheetId": int(SHEET_ID),  # 시트 ID는 숫자로 변환해야 함
                        "values": value
                    }
                ]
            }
            response = self.sheet.spreadsheets().values().append(
                spreadsheetId=SHEET_ID,
                range=SHEET_RANGE,
                value=body["resources"][0]["values"],
                body=body
            ).execute()
            return {"status": "success", "message": "데이터 저장 완료"}
        except Exception as e:
            return {"status": "error", "message": str(e)}

# 화면 캡처 함수
def capture_screen(region=None):
    """
    화면 전체를 캡처하거나 지정된 영역만 캡처합니다.
    """
    try:
        if region is None:
            screenshot = pyautogui.screenshot()
            image = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
            return image
        else:
            screenshot = pyautogui.screenshot(region=region)
            image = cv2.cvtColor(np.array(screenshot), cv2.COLOR_RGB2BGR)
            return image
    except Exception as e:
        raise Exception(f"화면 캡처 오류: {e}")

# 이미지 분류 함수
def classify_image(image_bgr):
    """
    YOLOv8 모델로 이미지를 분류합니다.
    """
    try:
        results = model(image_bgr)
        classified_objects = []
        for result in results:
            class_id = result.class_id
            confidence = result.confidence
            bbox = result.bounding_box
            classified_objects.append({
                "class_id": class_id,
                "confidence": float(confidence),
                "bbox": list(bbox)
            })
        return classified_objects
    except Exception as e:
        print(f"이미지 분류 오류: {e}")
        return []

# Flask 라우트 정의
@app.route('/capture-and-classify', methods=['POST'])
def capture_and_classify():
    """
    화면 캡처 후 즉시 분류하고 결과를 JSON으로 반환합니다.
    """
    try:
        image_data = capture_screen()
        results = classify_image(image_data)
        response = {
            "status": "success",
            "objects": results  # 분류된 객체 리스트 반환
        }
        # Google Sheets에 데이터 저장 (선택 사항)
        sheet_api = GoogleSheetsAPI()
        sheet_api.update_sheet(results)
        return jsonify(response)
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

@app.route('/capture', methods=['POST'])
def capture_only():
    """
    이미지만 캡처하여 Base64 형식으로 반환합니다.
    """
    try:
        image_data = capture_screen()
        _, buffer = cv2.imencode('.jpg', image_data)
        return jsonify({"status": "success", "image": buffer.tobytes()})
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

@app.route('/sheets-test', methods=['POST'])
def test_sheet_update():
    """
    Google Sheets API 테스트 함수
    """
    try:
        sheet_api = GoogleSheetsAPI()
        test_data = [{"Test": "Success", "Time": "2023-10-27"}]
        response = sheet_api.update_sheet(test_data)
        return jsonify(response)
    except Exception as e:
        return jsonify({"status": "error", "message": str(e)}), 500

if __name__ == '__main__':
    app.run(host='127.0.0.1', port=5000, debug=True)

코드에서 꼭 수정해야 하는 부분

  • 모델 경로: MODEL_PATH 변수를 실제 다운로드한 YOLOv8 모델 파일 경로로 수정해야 합니다.
  • Google Sheets ID 및 범위: SHEET_IDSHEET_RANGE 변수를 실제 Google Sheets 문서 ID와 데이터 저장 범위로 변경해야 합니다.
  • 인증 파일 경로: GOOGLE_SHEET_SERVICE_ACCOUNT_FILE 경로를 실제 서비스 계정 JSON 파일 경로로 수정해야 합니다.

실행 방법

  1. 터미널 실행:
    bash python app.py
  2. 웹 서비스 확인:
    서버가 정상적으로 실행되면 http://127.0.0.1:5000에서 확인할 수 있습니다.
  3. 테스트 엔드포인트 호출:
  4. 화면 캡처 및 분류 결과 확인: curl -X POST http://127.0.0.1:5000/capture-and-classify
  5. 이미지 캡처 결과 확인: curl -X POST http://127.0.0.1:5000/capture
  6. Google Sheets 테스트: curl -X POST http://127.0.0.1:5000/sheets-test

자주 막히는 부분

  1. Google Sheets 인증 문제:
  2. 오류 원인: service_account.json 파일 경로 오류 또는 권한 설정 불일치.
  3. 해결 방법: 파일 경로를 확인하고, Google Cloud Console에서 서비스 계정 권한을 정확히 설정하세요.
  4. 화면 캡처 오류:
  5. 오류 원인: PyAutoGUI가 캡처하는 화면 영역이 제한되거나 다른 애플리케이션에 의해 방해받을 수 있음.
  6. 해결 방법: 캡처 영역을 정확하게 설정하거나, 캡처 시 다른 애플리케이션이 방해되지 않도록 확인하세요.
  7. YOLOv8 모델 로드 실패:
  8. 오류 원인: 모델 파일이 잘못된 경로에 있거나 손상된 경우.
  9. 해결 방법: 모델 파일 경로를 확인하고, 모델 파일이 정상적으로 다운로드되었는지 확인하세요.

마무리

이 시스템을 구축하면 반복적인 이미지 분류 작업을 자동화하여 시간과 노력을 크게 절약할 수 있습니다. Google Sheets와의 연동은 데이터 관리와 추적을 용이하게 만들어줍니다. 직접 구현해보면서 다양한 시나리오에 맞게 시스템을 확장하고 최적화해보세요. 문제가 발생하면 오류 메시지를 주의 깊게 확인하고, 위에서 제시한 해결 방법을 참고하여 문제를 해결해보세요. 이러한 자동화 기술은 업무 효율성을 크게 향상시키는 데 큰 도움이 될 것입니다.

반응형
반응형

이 자동화가 필요한 상황

반복적인 업무 중 하나로, 매주 또는 매일 정기적으로 업데이트되는 엑셀 데이터를 서버에서 로컬 컴퓨터로 가져오고 이를 분석한 결과를 이메일로 자동 알림 받는 과정이 있습니다. 예를 들어, 마케팅 팀에서는 매주 월요일 아침에 지난 주 판매 데이터를 분석하고, 해당 결과를 팀 리더에게 이메일로 보내는 작업이 필요할 수 있습니다. 이러한 과정은 수동으로 이루어지므로 시간 소모적이고, 데이터 입력 오류 가능성이 높아 효율성이 떨어집니다. 자동화를 통해 이러한 반복 작업을 줄이고, 실시간 데이터 분석 결과를 빠르게 공유할 수 있습니다.

전체 흐름 먼저 이해하기

  1. 엑셀 데이터 읽기: Python 스크립트를 통해 엑셀 파일을 읽어들입니다.
  2. 데이터 분석: 읽어들인 데이터를 분석하고 요약 결과를 생성합니다.
  3. 결과 저장: 분석 결과를 텍스트 파일로 저장합니다.
  4. 이메일 발송: AutoHotkey 스크립트를 통해 저장된 결과를 이메일로 전송합니다.
  5. 스케줄링: AutoHotkey를 사용하여 정해진 시간에 Python 스크립트를 자동 실행합니다.

준비해야 할 것

설치해야 할 라이브러리 및 도구

  • Python: pandas, smtplib, email, openpyxl 라이브러리 설치
    bash pip install pandas openpyxl smtplib email
  • AutoHotkey: 공식 웹사이트에서 다운로드 및 설치
  • AutoHotkey 다운로드 링크

필요한 설정 파일

  • .env 파일: 민감 정보를 안전하게 관리하기 위한 환경 변수 파일
    bash # .env 파일 예시 EXCEL_FILE_PATH=C:/path/to/your/excel_file.xlsx SMTP_SERVER=smtp.gmail.com SMTP_PORT=587 SENDER_EMAIL=your_email@example.com SENDER_PASSWORD=your_app_password_here RECIPIENT_EMAIL=recipient_email@example.com DATA_COLUMN=데이터열이름 LOG_FILE_PATH=logs/automation_log.txt

코드 파일 준비

  • Python 스크립트 파일 (data_automation.py): 데이터 처리 및 분석 로직 포함
  • AutoHotkey 스크립트 파일 (automation_scheduler.ahk): 스케줄링 및 이메일 발송 로직 포함

핵심 코드 구현

Python 데이터 처리 스크립트 (data_automation.py)

이 코드는 엑셀 파일을 읽고 분석한 결과를 이메일로 전송하는 전체 과정을 다룹니다.

  #!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
[자동화 데이터 처리 시스템]
- 목적: 엑셀 데이터 정기 분석 및 결과 이메일 알림
- 기술 스택: pandas, smtplib, selenium (선택 사항)
- 실행 전 필수 설치: pip install pandas smtplib email

주의사항: 민감정보는 환경변수 파일(.env)에서 관리하세요!
"""

import os
import sys
import time
from datetime import datetime
from typing import Optional, Dict
import pandas as pd
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
import smtplib

try:
    from dotenv import load_dotenv
except ImportError:
    # dotenv 라이브러리가 없을 경우 기본 환경변수 처리
    load_dotenv = lambda: None

class DataAutomationSystem:
    """데이터 자동화 처리 시스템 클래스"""

    def __init__(self, config_path: str = '.env'):
        """
        초기화 메서드
        Args:
            config_path: 환경변수 파일 경로 (기본값: .env)
        """
        self.load_env = load_dotenv(config_path) if 'load_dotenv' in dir() else None
        self.summary_file = 'summary_output.txt'
        self.config = self._init_config()

    def _init_config(self) -> Dict[str, str]:
        """환경변수로부터 설정값 로드 및 기본값 설정"""
        try:
            if self.load_env:
                config = self.load_env()
            else:
                config = {}

            defaults = {
                'EXCEL_FILE_PATH': 'C:/path/to/your/excel_file.xlsx',
                'SMTP_SERVER': 'smtp.gmail.com',
                'SMTP_PORT': '587',
                'SENDER_EMAIL': '',
                'SENDER_PASSWORD': '',
                'RECIPIENT_EMAIL': '',
                'DATA_COLUMN': '데이터열이름',  # 분석할 열 이름
            }

            for key, value in defaults.items():
                env_key = key.upper()
                if self.load_env and self.load_env().get(env_key):
                    defaults[key] = self.load_env().get(env_key)
                elif os.getenv(env_key):
                    defaults[key] = os.getenv(env_key)

            return defaults

        except Exception as e:
            print(f"[오류] 환경변수 로드 실패: {e}")
            return defaults

    def read_excel_data(self) -> Optional[pd.DataFrame]:
        """
        엑셀 파일 읽기 (pandas 사용)

        Returns:
            DataFrame: 읽힌 엑셀 데이터 (성공 시)
            None: 파일 읽기 실패 시

        예외 처리:
            - FileNotFoundError: 파일이 존재하지 않을 경우
            - EmptyExcelError: 빈 엑셀 파일일 경우
        """
        try:
            excel_path = self.config['EXCEL_FILE_PATH']
            if not os.path.exists(excel_path):
                raise FileNotFoundError(f"엑셀 파일을 찾을 수 없습니다: {excel_path}")

            df = pd.read_excel(excel_path, engine='openpyxl')
            if df.empty:
                print("[경고] 엑셀 파일이 비어있습니다.")
                return None

            print(f"[정보] 파일: {excel_path}")
            print(f"[정보] 행 수: {len(df)}, 열 수: {len(df.columns)}")
            print(f"[정보] 데이터 미리보기:\n{df.head()}")

            return df

        except FileNotFoundError as e:
            print(f"[에러] 파일 없음: {e}")
            return None
        except Exception as e:
            print(f"[에러] 엑셀 읽기 실패: {e}")
            return None

    def analyze_data(self, df: pd.DataFrame) -> Dict[str, object]:
        """
        데이터 분석 및 요약 생성

        Args:
            df: pandas DataFrame 객체

        Returns:
            Dict: 분석 결과 딕셔너리
                - summary: 분석 요약 문자열
                - timestamp: 분석 시간
                - column_stats: 각 열의 통계 정보
        """
        try:
            analysis_time = datetime.now().strftime('%Y-%m-%d %H:%M:%S')
            column_stats = {}
            summary_parts = []

            numeric_cols = df.select_dtypes(include=['number']).columns
            for col in numeric_cols:
                try:
                    col_stats = {
                        'col_name': col,
                        'mean': df[col].mean(),
                        'std': df[col].std(),
                        'min': df[col].min(),
                        'max': df[col].max(),
                        'count': df[col].count()
                    }
                    column_stats[col] = col_stats
                    summary_parts.append(
                        f" - {col} 평균: {col_stats['mean']:.2f}"
                    )
                except Exception as e:
                    print(f"[경고] 열 '{col}' 분석 실패: {e}")
                    continue

            # 비숫자형 열도 포함
            for col in df.columns:
                if col not in numeric_cols:
                    try:
                        if df[col].dtype == 'object':
                            column_stats[col] = {
                                'type': 'object',
                                'unique_count': df[col].nunique(),
                                'description': f"카테고리 데이터 ({df[col].nunique()}개)"
                            }
                    except Exception as e:
                        pass

            if summary_parts:
                summary = (
                    f"📊 데이터 분석 결과\n"
                    f"==============\n"
                    f"분석 시간: {analysis_time}\n"
                    f"==============\n"
                    f"\n📈 주요 지표:\n"
                    + '\n'.join(summary_parts)
                )
            else:
                summary = "❗ 분석할 숫자형 데이터 없음\n"
                summary += f"==============\n"
                summary += f"분석 시간: {analysis_time}\n"
                summary += f"==============\n"

            return {
                'summary': summary,
                'timestamp': analysis_time,
                'column_stats': column_stats
            }

        except Exception as e:
            print(f"[에러] 데이터 분석 실패: {e}")
            return {
                'summary': '❗ 데이터 분석 중 오류 발생\n'
                           '==============\n'
                           f"오류 메시지: {str(e)}\n"
                           f"발생 시간: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}",
                'timestamp': datetime.now().strftime('%Y-%m-%d %H:%M:%S'),
                'column_stats': {}
            }

    def save_summary(self, analysis_result: Dict[str, object]) -> bool:
        """
        분석 결과를 텍스트 파일로 저장

        Args:
            analysis_result: 분석 결과 데이터

        Returns:
            bool: 저장 성공 (True) / 실패 (False)
        """
        try:
            if not analysis_result:
                print("[경고] 저장할 분석 결과가 없음.")
                return False

            file_path = self.summary_file
            with open(file_path, 'w', encoding='utf-8') as file:
                file.write(analysis_result['summary'])

            print(f"[성공] 분석 결과 저장 완료: {file_path}")
            return True

        except Exception as e:
            print(f"[에러] 결과 저장 실패: {e}")
            return False

    def send_email(self, analysis_result: Dict[str, object]) -> bool:
        """
        이메일 발송 기능

        Args:
            analysis_result: 분석 결과 데이터

        Returns:
            bool: 발송 성공 (True) / 실패 (False)
        """
        try:
            if not analysis_result:
                print("[경고] 발송할 분석 결과가 없음.")
                return False

            smtp_server = self.config['SMTP_SERVER']
            smtp_port = self.config['SMTP_PORT']
            sender_email = self.config['SENDER_EMAIL']
            sender_password = self.config['SENDER_PASSWORD']
            recipient = self.config['RECIPIENT_EMAIL']

            if not sender_password:
                print("[에러] 이메일 비밀번호가 비어있습니다.")
                return False

            message = MIMEMultipart()
            message['From'] = sender_email
            message['To'] = recipient
            message['Subject'] = '📊 데이터 분석 요약 알림 - 자동화 시스템'

            html_content = f"""
            <html>
            <body style="font-family: Arial, sans-serif;">
            <h2 style="color: #2c3e50;">📊 자동 데이터 분석 결과</h2>
            <p style="color: #34495e;">
            안녕하세요,<br><br>
            요청하신 엑셀 파일의 분석 결과를 정리해 드립니다.
            </p>

            <div style="background-color: #f8f9fa; padding: 15px; border-radius: 5px; margin: 20px 0;">
            <h3 style="color: #2980b9;">🔍 분석 내용</h3>
            <pre style="white-space: pre-wrap; font-size: 14px;">
            {analysis_result['summary']}
            </pre>
            </div>

            <p style="color: #95a5a6; font-size: 12px;">
            — 자동화 데이터 처리 시스템<br>
            발생 시간: {analysis_result['timestamp']}
            </p>
            </body>
            </html>
            """

            message.attach(MIMEText(html_content, 'html'))

            server = smtplib.SMTP(smtp_server, int(smtp_port))
            server.starttls()
            server.login(sender_email, sender_password)
            server.send_message(message)
            server.quit()

            print(f"[성공] 이메일 발송 완료 ({recipient})")
            return True

        except Exception as e:
            print(f"[에러] 이메일 발송 실패: {e}")
            return False

    def run(self):
        """
        메인 실행 함수
        데이터 읽기 → 분석 → 저장 → 이메일 발송 순차 처리
        """
        try:
            print("=" * 60)
            print("🚀 자동화 데이터 처리 시스템 실행 시작")
            print("=" * 60)

            # 단계 1: 엑셀 데이터 읽기
            print("\n[단계 1/4] 엑셀 파일 읽기...")
            df = self.read_excel_data()

            if df is None:
                print("[종료] 엑셀 파일 읽기 실패로 조기종료")
                return

            # 단계 2: 데이터 분석
            print("\n[단계 2/4] 데이터 분석 수행...")
            analysis_result = self.analyze_data(df)

            # 단계 3: 결과 저장
            print("\n[단계 3/4] 결과 파일 저장...")
            save_success = self.save_summary(analysis_result)

            if not save_success:
                print("[경고] 결과 저장 실패")

            # 단계 4: 이메일 발송
            print("\n[단계 4/4] 이메일 발송...")
            send_success = self.send_email(analysis_result)

            # 최종 상태 보고
            print("\n" + "=" * 60)
            print("✅ 자동화 처리 완료")
            print("=" * 60)

            # 다음 실행까지 대기 (1 분)
            time.sleep(60)

        except KeyboardInterrupt:
            print("\n[종료] 사용자 중지 명령어 수신")
        except Exception as e:
            print(f"\n[에러] 예기치 않은 오류 발생: {e}")
            import traceback
            traceback.print_exc()
            sys.exit(1)

# 메인 실행 - 실제 실행 시 주석 해제
if __name__ == '__main__':
    # 환경 설정 파일 생성
    env_file = '.env'
    if not os.path.exists(env_file):
        with open(env_file, 'w', encoding='utf-8') as f:
            f.write("""# === 환경변수 설정 ===
# EXCEL_FILE_PATH=C:/path/to/your/excel_file.xlsx
# SMTP_SERVER=smtp.gmail.com
# SMTP_PORT=587
# SENDER_EMAIL=your_email@example.com
# SENDER_PASSWORD=your_app_password_here
# RECIPIENT_EMAIL=recipient_email@example.com
# DATA_COLUMN=데이터열이름
# LOG_FILE_PATH=logs/automation_log.txt
""")
        print(f"[정보] 환경변수 파일 생성됨: {env_file}")

    system = DataAutomationSystem()
    system.run()

AutoHotkey 스케줄링 및 이메일 스크립트 (automation_scheduler.ahk)

이 코드는 AutoHotkey를 사용하여 Python 스크립트를 스케줄링하고 이메일 발송 기능을 구현합니다.

  #Requires AutoHotkey v1.1
#SingleInstance Force
#NoEnv  ; 빠른 실행을 위해 환경 변수 설정 비활성화
SetWorkingDir %A_ScriptDir%
#Include %A_ScriptDir%\EnvHelper.ahk
#Include %A_ScriptDir%\EmailHelper.ahk

--- 환경변수 로드 이메일 헬퍼 설정 메인 스케줄러 알림 창 스크립트 종료 전 처리 ---
OnExit:
    # 로그 기록 (선택 사항)
    FileAppend, %A_ScriptDir%\logs\automation_log.txt, Automating System Execution at `DateTime`, User initiated shutdown
    Return

이메일 헬퍼 스크립트 (EmailHelper.ahk)

이 스크립트는 이메일 발송에 필요한 SMTP 연결을 설정합니다.

  #NoEnv  ; 빠른 실행을 위해 환경 변수 설정 비활성화
SetWorkingDir %A_ScriptDir%

#SMTP 설정 함수
SetSMTP(server, port) {
    Global SMTP_SERVER := server
    Global SMTP_PORT := port
    return
}

#이메일 발송 함수
SendEmail(to, subject, body) {
    Global SMTP_SERVER := !SMTP_SERVER!
    Global SMTP_PORT := !SMTP_PORT!
    Global SENDER_EMAIL := !SENDER_EMAIL!
    Global SENDER_PASSWORD := !PASSWORD!

    ; SMTP 서버 연결 설정
    SMTPServer := SMTP_SERVER
    SMTPPort := SMTP_PORT

    Mail := Socket Open(SMTPServer, SMTPPort)
    if (Mail = "") {
        MsgBox, SMTP 연결 실패!
        return False
    }

    ; SMTP 인증 시도
    Socket Send(Mail, "EHLO localhost")
    Socket ReceiveLine(Mail, Response)

    if (Response !~ *"250") {
        MsgBox, SMTP 인증 실패!
        Socket Close(Mail)
        return False
    }

    ; STARTTLS (보안 연결)
    Socket Send(Mail, "STARTTLS")
    Socket ReceiveLine(Mail, Response)
    if (Response !~ *"200") {
        MsgBox, STARTTLS 실패!
        Socket Close(Mail)
        return False
    }

    ; 인증 완료 후 로그인
    Socket Send(Mail, "AUTH LOGIN")
    Socket Send(Mail, "%EMAIL%:%PASSWORD%")
    Socket ReceiveLine(Mail, Response)
    if (Response !~ *"235") {
        MsgBox, 인증 실패!
        Socket Close(Mail)
        return False
    }

    ; 이메일 전송
    MailBody := "From: " SENDER_EMAIL "\r\nTo: " to "\r\nSubject: " subject "\r\n\r\n" body "\r\n.\r\n"
    Socket Send(Mail, MailBody)
    Socket Send(Mail, "QUIT")
    Socket Close(Mail)

    MsgBox, 이메일 성공적으로 발송되었습니다!
    return True
}

코드에서 꼭 수정해야 하는 부분

  1. 환경 변수 설정: .env 파일에서 실제 경로와 이메일 정보로 수정해야 합니다.
    ini EXCEL_FILE_PATH=실제 엑셀 파일 경로 SMTP_SERVER=smtp.gmail.com 또는 다른 SMTP 서버 주소 SMTP_PORT=587 (Gmail 사용 시) SENDER_EMAIL=발신 이메일 주소 SENDER_PASSWORD=앱 비밀번호 (2단계 인증 필요 시) RECIPIENT_EMAIL=수신 이메일 주소 DATA_COLUMN=분석할 엑셀 열 이름
  2. 파일 경로: Python 스크립트와 AutoHotkey 스크립트의 파일 경로를 실제 위치에 맞게 수정해야 합니다.
    python excel_path = 'C:/path/to/your/excel_file.xlsx'
  3. 이메일 발송 설정: AutoHotkey 스크립트에서 이메일 발송 부분을 테스트하여 SMTP 서버 설정이 올바르게 이루어져 있는지 확인해야 합니다.
    autohotkey SendEmail(RECIPIENT_EMAIL, "데이터 분석 요약 알림", analysis_result['summary'])

실행 방법

터미널에서 실행하기

  1. Python 가상 환경 활성화 (필요한 경우):
    bash python -m venv automation_env source automation_env/Scripts/activate # Windows # 또는 automation_env\Scripts\activate # macOS/Linux
  2. 라이브러리 설치:
    bash pip install pandas openpyxl smtplib email
  3. 환경 변수 파일 생성:
  4. .env 파일을 생성하고 위에 제시된 내용을 수정합니다.
  5. AutoHotkey 스크립트 실행:
  6. AutoHotkey 스크립트를 실행하여 스케줄링을 설정합니다. 단축키 (Ctrl+Alt+1 또는 Ctrl+Alt+2)를 설정하여 Python 스크립트를 자동 실행하도록 합니다.
    bash compile automation_scheduler.ahk ; AutoHotkey 컴파일 명령 (필요한 경우) start automation_scheduler.ahk
  7. Python 스크립트 직접 실행:
  8. 필요에 따라 직접 Python 스크립트를 실행하여 테스트할 수 있습니다.
    bash python data_automation.py

자주 막히는 부분

  1. 환경 변수 설정 오류: .env 파일에 정확한 경로와 정보가 입력되지 않아 설정이 실패할 수 있습니다. .env 파일 내용을 철저히 확인하세요.
  2. SMTP 서버 인증 실패: 이메일 발송 시 SMTP 서버 인증 오류가 발생할 수 있습니다. 특히 Gmail 앱 비밀번호 설정을 확인하세요.
  3. 파일 경로 오류: 엑셀 파일 경로가 잘못 설정되어 있으면 Python 스크립트가 파일을 찾지 못합니다. 실제 파일 경로로 수정하세요.
  4. AutoHotkey 단축키 설정: 단축키 설정이 제대로 되지 않아 스크립트가 실행되지 않을 수 있습니다. AutoHotkey 스크립트를 다시 확인하고 필요에 따라 수정하세요.

마무리

이 자동화 시스템을 통해 엑셀 데이터의 정기적인 분석 결과를 이메일로 간편하게 알림 받을 수 있습니다. 마케팅 팀이나 데이터 분석 팀에서 특히 유용하게 활용할 수 있으며, 스크립트와 설정을 적절히 조정하면 다양한 업무 환경에 적용할 수 있습니다. 정기적인 시스템 점검과 테스트를 통해 안정성을 유지하고, 필요에 따라 분석 로직과 이메일 템플릿을 커스터마이징하여 더욱 효율적으로 사용할 수 있습니다.

반응형
반응형

데이터 수집부터 분석까지, Python으로 완성하는 자동 데이터 파이프라인 구축하기

서론

매일 폭발적으로 증가하는 데이터 속에서 수작업으로 데이터를 수집하고 분석하는 것은 시간 낭비일 뿐 아니라 오류 발생 가능성도 높습니다. 이 글에서는 Python을 활용하여 자동 데이터 수집 및 분석 파이프라인을 구축하는 방법을 실무적으로 안내합니다. 이를 통해 독자 여러분은 직접 데이터를 자동으로 수집하고 분석하여 더욱 효율적인 의사 결정을 지원할 수 있는 시스템을 구축할 수 있습니다.

본론

단계 1: 웹 크롤링을 통한 데이터 수집

첫 번째 단계는 웹 페이지에서 필요한 데이터를 자동으로 수집하는 것입니다. 이를 위해 BeautifulSoupRequests 라이브러리를 사용하여 웹 페이지를 파싱하고 데이터를 추출합니다. 이후 Pandas를 이용해 데이터를 구조화하고 SQLite 데이터베이스에 저장합니다.

  # 필요한 라이브러리 import
import requests
from bs4 import BeautifulSoup
import pandas as pd
import sqlite3

def fetch_web_data(url):
    """
    주어진 URL에서 웹 페이지 데이터를 가져오고 HTML 문자열로 반환합니다.
    네트워크 오류 발생 시 None을 반환합니다.
    """
    try:
        response = requests.get(url)
        response.raise_for_status()  # HTTP 오류 처리
        return response.text
    except requests.RequestException as e:
        print(f"[ERROR] 웹 페이지 요청 실패: {e}")
        return None

def parse_html_table(html_content):
    """
    HTML 내용에서 테이블 데이터를 추출하여 Pandas DataFrame으로 변환합니다.
    """
    try:
        soup = BeautifulSoup(html_content, 'html.parser')
        table = soup.find('table', attrs={'class': 'wikitable'})  # 테이블 태그 찾기
        if not table:
            print("[WARNING] 테이블 데이터를 찾을 수 없습니다.")
            return pd.DataFrame()

        headers = [header.text.strip() for header in table.find_all('th')]
        data = []
        for row in table.find_all('tr')[1:]:  # 헤더 제외
            cols = [ele.text.strip() for ele in row.find_all('td')]
            data.append(cols)

        df = pd.DataFrame(data, columns=headers)
        return df
    except Exception as e:
        print(f"[ERROR] HTML 파싱 중 오류 발생: {e}")
        return pd.DataFrame()

# 예시 사용
url = 'https://example.com/data'  # 크롤링 대상 URL 설정
html_data = fetch_web_data(url)
if html_data:
    df = parse_html_table(html_data)
    print(df)  # DataFrame 출력

    # SQLite 데이터베이스에 저장
    conn = sqlite3.connect('data_collection.db')
    df.to_sql('scraped_data', conn, if_exists='replace', index=False)
    conn.close()
    print("[SUCCESS] 데이터가 SQLite 데이터베이스에 저장되었습니다.")

단계 2: 데이터 분석 및 시각화

수집된 데이터를 분석하고 결과를 시각화하여 이해하기 쉽게 표현하는 단계입니다. Pandas를 이용해 데이터를 분석하고 Matplotlib을 사용하여 차트를 생성합니다.

  import matplotlib.pyplot as plt

def analyze_and_visualize(df):
    """
    데이터프레임을 분석하고 막대 차트로 시각화합니다.
    """
    if df.empty:
        print("[WARNING] 분석할 데이터가 없습니다.")
        return

    # 예시: 숫자 데이터의 평균 계산
    numeric_columns = df.select_dtypes(include=['float64', 'int64']).columns
    if numeric_columns.empty:
        print("[WARNING] 분석 가능한 숫자형 열이 없습니다.")
        return

    mean_value = df[numeric_columns[0]].mean()
    print(f"[ANALYSIS] 평균값: {mean_value}")

    # 시각화
    plt.figure(figsize=(10, 6))
    df[numeric_columns[0]].head(10).plot(kind='bar', title='데이터 분석 결과')
    plt.ylabel('값')
    plt.xticks(rotation=45)  # x축 라벨 회전
    plt.tight_layout()

    # 차트 저장
    plt.savefig('data_analysis_chart.png')
    print(f"[SUCCESS] 분석 차트가 'data_analysis_chart.png' 로 저장되었습니다.")
    plt.show()

# 예시 사용
# 데이터베이스에서 데이터 로드
conn = sqlite3.connect('data_collection.db')
df = pd.read_sql_query("SELECT * FROM scraped_data", conn)
conn.close()

analyze_and_visualize(df)

단계 3: 스케줄링을 통한 자동화

마지막으로, 매일 특정 시간에 자동으로 데이터 수집 및 분석 파이프라인을 실행하도록 schedule 라이브러리를 활용합니다.

  import schedule
import time

def run_pipeline():
    """
    데이터 수집, 저장, 분석 및 시각화 파이프라인 전체를 실행합니다.
    """
    print("\n--- [MAIN PIPELINE START] ---")

    # 데이터 수집
    html_data = fetch_web_data('https://example.com/data')
    if not html_data:
        print("[CRITICAL] 데이터 수집 실패로 파이프라인 중단.")
        return

    # 데이터 파싱 및 저장
    df = parse_html_table(html_data)
    if df.empty:
        print("[WARNING] 데이터 파싱 실패.")
        return

    save_to_sqlite(df)

    # 데이터 분석 및 시각화
    analyze_and_visualize(df)

    print("--- [MAIN PIPELINE END] ---\n")

# 스케줄 설정
schedule.every().day.at("15:00").do(run_pipeline)  # 매일 오후 3시 실행 설정

# 메인 루프 시작
print("[INFO] 스케줄러가 시작되었습니다. 매일 오후 3시에 자동 실행됩니다.")

try:
    while True:
        schedule.run_pending()
        time.sleep(1)
except KeyboardInterrupt:
    print("\n[INFO] 사용자 입력으로 스크립트 정지.")

결론

위에서 소개한 파이프라인을 통해 매일 특정 시간에 자동으로 데이터를 수집하고 분석하여 의사결정에 필요한 통찰력을 얻을 수 있습니다. 파이프라인 구축 시 다음과 같은 팁을 참고하세요:

  • 데이터 소스구조에 따라 파이프라인을 적절히 조정하세요.
  • 오류 처리로깅을 추가하여 시스템의 안정성을 높이세요.
  • 파이프라인을 확장하여 더 많은 데이터 소스나 복잡한 분석 작업을 지원할 수 있도록 설계하세요.

이러한 방법론을 통해 실무에서 바로 활용 가능한 자동 데이터 수집 및 분석 시스템을 구축할 수 있습니다.

반응형
반응형

다운로드 파일은 글 아래 설명 이후에 있습니다.

설명을 꼭 읽어보세요!

 

 

 

안녕하세요! 엄청 오랫만에 플 만들게 되었네요!

 

아스달연대기 보스 리젠 타이머 입니다!

 

일상이 바빠서 게임이든 뭐든 아무것도 못했는데

이번에 아스달 연대기가 새로 나왔다고 해서 했는데 재밌더라구요

 

플레이중에 보스를 30회 잡으면 희귀 상자를 준다고 하길래 열심히 잡으려는데

젠을 매번 놓쳐서 그냥 Addon같은 프로그램을 만들어 봤습니다!

 

 

해당 프로그램을 켰을때 이미지 입니다!

 

여기서 예를 들어 투칸 보스를 잡은 뒤 투칸 이미지를 클릭하시게 되면

 

 

이런식으로 리젠 남은시간을 초단위로 알려주게 됩니다!

 

그 후 남은시간이 3분(180초)이 남을 경우에는 알람이 울리게 됩니다.

 

알람은 컴퓨터 자체 비프음을 울리게 되고 2초간 지속 됩니다.

 

다른것에 집중 하다가도 알람을 듣고 보스 잡으러 움직여 주시면 되겠죠?! ㅎㅎ

 

아스달연대기 보스 리젠 타이머는 pc프로그램임을 참고 해주시고

서버에서 보스컷 시간을 받아와서 젠 시간을 알려주는게 아니라

각자 개인이 보스컷을 하고 클릭을 해줘서 카운트를 하는 프로그램입니다.

그냥 일종의 보조 타이머라고 보시면 됩니다!

 

다운로드 많이 받아가셔요!

 

Arthdal_Addon.zip
0.58MB

 

한 폴더에 꼭 전체 압축 풀고 사용 해주세요!

반응형
반응형

체험판 다운로드는 글 아래쪽에 있습니다!!!

천천히 글들을 읽어 보시고 체험판 사용을 권장 드립니다

 

 


22-06-20 업데이트 내역

-프리미엄 버전 업데이트

#비활성 프로그램 완성 되었습니다.

   -비활성 프로그램은 프로그램 사용중 인터넷과 같이

    다른작업을 하여도 백그라운드에서 사냥을 계속 하고 있습니다.

 

 

#활성화 프로그램 추가 업데이트 되었습니다.

   -기존 공개한 사냥-마을-분해-사냥터이동

    시스템에서 자잘한 오류들 수정 했습니다

 

   -기존 설정된 맵 이외에도 다른 지역, 다른 사냥터위치까지

    커스터마이징으로 사용 가능하도록 업데이트 되었습니다.


22-06-19 업데이트 내역

-블로그에서 체험판 다운로드 및 사용 가능합니다

-체험판은 15분간 사용후 프로그램이 종료 됩니다.

 

-프리미엄 버전이 업데이트 되었습니다.

#프리미엄 버전의 기능 소개

  =시간 제한 없이 사용 가능합니다

  =블로그로 자동 연결 되는것들이 사라집니다.

 

(녹스에서 특정 셋팅이 가능하신 분들이 사용 가능한 기능)

  =맵에서 사냥하고 마을로 복귀 - 대장장이 분해 - 사냥터 복귀

    하는 기능이 업데이트 되었습니다.

(녹스 셋팅은 블로그 글 하단에 기재 하겠습니다.)

 


 

 


22-06-10 업데이트 내역

-설정하신 값들을 저장 할 수 있도록 저장하는 기능을 추가했습니다

(단축키 사용여부, 단축키셋팅값, 딜레이값)

(저장한 값은 프로그램 시작시 자동으로 불러오기 합니다.)


디아블로 이모탈 오픈소식을 듣고 열심히 게임을 했습니다

 

그런데 All수동 게임이라서

타 모바일게임은 잘때도 캐릭터를 성장 시킬수 있지만

디아블로이모탈은 할 수가 없더라구요 ㅠ

 

 

그래서 잘때도 캐릭터를 성장 시킬수 있도록 보조 프로그램을 만들었습니다.

 

블루스택과 PC버전에서 사용 가능하나

PC버전에서는 논타겟공격이 불가능해서

블루스택을 사용했습니다

 

(추후 PC버전에서 논타겟공격이 수정되면 바로 사용가능한 프로그램입니다.)

 

위 프로그램은 제자리에서 사냥, 버프스킬보조용 체험판 프로그램 입니다.

 

 

저는 디아블로이모탈에서 수도승으로 플레이를 하였는데

필드에서 제자리에 두고

용오름,칠면공격,보호막,방어진

이렇게 스킬 4가지를 셋팅하고 사냥하였더니

밤새 아주 잘 돌아갔습니다

(줍기 기능으로 인해

밤새 전설템을 1~2개는 꼭 먹어두더라구요)

 

그리고 균열이나 미친왕을 플레이할때

보호막켜는걸 매 타이밍 마다 잊지않고 누르기는 쉽지 않았는데

보호막 스킬만 자동으로 돌려주고 플레이를 하니

잊지않고 계속 돌려줄수 있어서 편했습니다

 

 

프로그램이 돌아가는동안

밥먹고 골프도치고 커피도 한잔하고

집에 돌아오니 전설템 1~2개씩 먹는건 일도 아니더라구요

 

해당 프로그램은

이걸로 다운 받으시면 됩니다.

 

DiaM-체험판.zip
13.53MB

기타 문의사항은 프로그램에서 연결되는 오픈채팅에서 문의주세요!

 

 


프리미엄 버전 사용시

녹스에서 해당 셋팅이 가능한 분들은

사냥-귀환-분해-복귀

시스템을 이용 가능합니다.

이용에 참고 바랍니다.


 

[녹스 셋팅]
#성능탭
4코어 8192MB 메모리
그래픽 모드 =호환+모드
#해상도설정
태블릿 1280x720


#핸드폰탭
휴대폰모델설정 = 삼성갤럭시 노트 10+


#인터페이스 탭
기존위치와 사이즈 유지 체크
고정된 윈도우 사이즈 체크

 

반응형
반응형

1편 보기 : https://nadohungo.tistory.com/28

 

쿠팡파트너스 자동프로그램 (T스토리) 21.09.29

글의 아래에도 2편 링크가 있습니다. 2편링크 : https://nadohungo.tistory.com/29 쿠팡파트너스 자동프로그램 (T스토리버전) 2편 (업그레이드) 후아 뭔가 하나에 꽂히니 또 이것만 보고있네요 ㅠ 이번엔 어

nadohungo.tistory.com

 

2편 보기 : https://nadohungo.tistory.com/29

 

쿠팡파트너스 자동프로그램 (T스토리버전) 2편 (업그레이드)

후아 뭔가 하나에 꽂히니 또 이것만 보고있네요 ㅠ 이번엔 어제 만든 프로그램에서 업그레이드를 하였습니다. 어제 만든건 제가 수기로 써야할것이 1. 파트너스링크 2. 상품이름 3. 키워드 4. 상

nadohungo.tistory.com

 

2편에 이어서 완성편을 쓰기전에

몇일간 테스트를 했습니다

 

네이버 블로그는 하루에 글 발행이 200개로 제한 되어있는데

200개를 업로드하는 동안 발생하는 상황에 모두 대응해야하고

프로그램이 자동으로 쭉쭉쭉 돌아가야해서

약 2일에 걸쳐 멈춤없이 200개 발행을 하도록 완성했습니다

 

귀찮아서 폼은 수정하지 않고 그냥 사용 하였습니다

상품 순위와 로켓배송은 굳이 사용 안해도 될거같아서

사용을 하지 않지만 귀찮아서 수정하지 않았죠 ㅎㅎ

 

프로그램이 구동 되는 순서 입니다

 

1. 메모장에 적힌 약 3000여개의 키워드를 처음부터 순차적으로 읽어냅니다.

 

2, 쿠팡파트너스 홈에서 자동으로 해당 키워드를 검색하여,

상품 링크를 받아옵니다.

(이때, 로그인,상품없슴등의 상황에 모두 대비 하였습니다)

 

3. 발급 받은 쿠파스 상품링크를 자동으로 리디렉션우회링크로 변환합니다.

 

4.해당 링크에서 상품이름,상품썸네일,상품가격의 정보를 받아옵니다.

 

5. 쿠팡파트너스에서 검색한 상품의 키워드를 이용하여

연관검색 키워드를 모두 받아옵니다.

 

6. 네이버 블로그에 글쓰기를 합니다

 

7. 제목입력을 해줍니다

 

8. 해당 상품의 썸네일을 업로드 하고

저작권문제를 해결하기 위해 이미지 편집을 조금 해줍니다.

 

9. 글 내용을 써줍니다

(상품내용이 변경될 수 있어서 작성시간을 적어줍니다)

(상품 가격을 써줍니다)

(링크만 있으면 거부감이 드니, 하이퍼링크를 만들어 줍니다)

 

10. 글 발행전 태그입력에 자동으로 받아온 상품의 연관검색어를 모두 태그입력 해줍니다

 

11. 글발행!

 

이렇게 1사이클로 하였고

 

30분마다 쿠팡파트너스 재로그인하는것도 대응하였고

상품이 없는것도 대응하였습니다.

 

글발행까지 생기는 인터넷딜레이 현상에 꼬이는 부분도

쉬는시간을 몇초씩 더 주어서 꼬이지 않게 만들었습니다.

 

그래서 꼬이지 않고 여유롭게 돌아갈 수있도록 만들고 나니

1사이클을 도는데 2분 조금 더 걸리더라구요

그냥 넉넉하게 1사이클=3분 정도로 생각하고 만들었습니다

1시간에 20개 가량의 블로그포스팅을

 

10시간 조금 안되니 200개의 글을 써주었더라구요

 

그래서 매일 자기전에 시작을 눌러놓으면

아침에 일어나면 200개의 글 발행을 모두 한 모습을 보았습니다

 

 

당연히 블로그 저품질은 생각하고 만들었는데

연관검색어 해시태그를 최대한 넣어 주었더니

 

네이버에서 검색되어 유입되는것 이상으로

ZUM이나 다음, 기타 사이트등에서 많은 유입이 생겼습니다

 

.

.

그리 하여 현재 1700개의 글이 발행 되어있는데

(약 1100개 정도는 해시태그 삽입을 안했어요)

(쿠파스 1일 클릭수 약 6~700회 [그중 제가 클릭 횟수 약 200회])

 

드디어 약 5일만에 첫 구매자가 생겼더라구요

아무래도 디테일한 상품 소개나, 핫딜 소개등이 아닌

단순 상품 정보만 툭 쓴 글이라 그런지 구매까지 확실하게는 일어나지 않았어요

 

아마 저품질을 생각하고 한거다 보니

질보다는 양으로 승부한다라는 생각으로

천천히 쌓고 있습니다

 

하루 200개의 포스팅

한달이면 6,000개의 포스팅,

1년이면 2,190,000개의 포스팅이 되겠네요

 

 

 

 

 

 

상품 키워드는 3000여개로 넉넉한 편이지만 좀 더 채워가고 있습니다!

예를 들면 새로 출시하는 아이폰이나 갤럭시등의 키워드나

그와 관련한 케이스나

새로 유행하는 키워드등을 더 추가해서 말이죠

 

1년간 잠들기전에만 켜주고 잠들면

200만개의 뿌린 씨앗들이 엄청난 성과를 거두어 줄지도 모르겠네요

 

오토핫키에 관심이 있거나

이 프로그램에 대해 궁금하신분들이 있다면

언제든지 아래의 오픈카톡으로 질문주세요!

공부하시는 분들이라면 정답을 알려드리진 않치만

힌트를 많이 드릴게요!

.

.

 

아래는 저와의 1:1 오픈 카톡입니다

https://open.kakao.com/o/sq3PTnCd

 

일상편함

일상편함

open.kakao.com

 

 

반응형
반응형

쿠팡파트너스 자동프로그램 완성버전 (네이버블로그 글발행)

↓아래 링크에서 확인 가능합니다

https://nadohungo.tistory.com/30

 

쿠팡파트너스 자동프로그램 (네이버블로그) - 완성

1편 보기 : https://nadohungo.tistory.com/28 쿠팡파트너스 자동프로그램 (T스토리) 21.09.29 글의 아래에도 2편 링크가 있습니다. 2편링크 : https://nadohungo.tistory.com/29 쿠팡파트너스 자동프로그램 (T스..

nadohungo.tistory.com

.

.

.

 

후아 뭔가 하나에 꽂히니 또 이것만 보고있네요 ㅠ

 

이번엔 어제 만든 프로그램에서 업그레이드를 하였습니다.

 

어제 만든건 제가 수기로 써야할것이

1. 파트너스링크

2. 상품이름

3. 키워드

4. 상품가격

5. 상품 순위

까지 다 적어주어야했는데요

 

먼저 사진을 보시면

이제 이렇게 손댈곳이 없는건 사용자가 수정하지 못하도록

블럭처리 하였습니다

 

.

.

 

 

하루동안 업그레이드 한 버전은

파트너스링크만 적어주시면

 

자동으로 상품이름, 상품가격 등의 정보를 수집하고

자동으로 우회된 리디렉션링크를 생성합니다

 

우회된 링크를 사용하는 이유는

티스토리, 네이버 블로그 등에서 쿠팡 링크를 사용한다면

저품질이나 광고성으로 인하여 블로그 정지를 받을 수 있기 때문에

우회된 링크를 통하여 우회링크를 클릭시 바로 쿠팡사이트로 이동

할 수 있도록 해주어야 하기 때문에 자동으로 우회링크를 만들어주게 됩니다

.

.

 

아래 이미지는 파트너스로 생성된 링크 입력시

자동으로 상품정보를 수집한것을 보여드리기 위한 예시용 이미지입니다

해당 파트너스링크는 이미지를 수정하였습니다

 

 

이렇게 5시간을 투자하여 상품정보 크롤링을 만들었지만

아직 작업 하지 않은건

상품 순위

로켓배송여부

상품 키워드

3가지는 작업하지 않았습니다

 

이후 또 작업을 하게 되면

상품 순위 -> 상품리뷰수

상품키워드 -> 해시태그용

로켓배송여부 -> 일반,로켓,로켓와우,프레시

이렇게 4가지로 나눠보려고합니다

 

그런데 이건 쿠팡파트너스 api를 발급 받으면 바로 해결될 문제라서

지금 당장 할 생각은 아직 없네용 ㅎㅎ

 

파트너스 api는 상품이 15만원 이상 팔려야지 api를 제공해준다고 하는데

언제 팔아볼지 모르겠네요 ㅎㅎ

아직 0원입니다 ㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋㅋ

 

 

이제 작업 해보려고하는게

 

네이버에 글을 깔끔하게 써서 자동으로 올리는 기능

 

메모장이나 엑셀을 통하여 링크만 꾹꾹 눌러담아 놓으면

하루종일 자동으로 해당 링크의 정보를 바탕으로 글을 계속 쓰는 기능

(이게 된다면 서버에 링크만 계속 담아 두면 실시간으로 계속 링크 업데이트 등 가능)

 

판매 상품의 썸네일 가져와서 이미지 편집을 자동으로 하여

블로그 글에 편집된 상품 이미지를 올리는 기능

(그냥 쿠팡에서 이미지를 가져와 올리면 저작권 위반 됩니다)

 

아마 네이버에 글 계속 올리는건 오늘 안에 마무리 될듯 합니다!

 

그럼 또 업데이트 하러 갈테니 자주 구경와주세요!

 

아 그리고 또 제가 만들어 봤으면 하는거 댓글로 적어주세요

시간이 되면 한번 만들어 볼게요!

 

.

.

 

궁금하신점이나 공부를 하고싶으신분들은

https://open.kakao.com/o/sq3PTnCd

 

일상편함

일상편함

open.kakao.com

이곳에 오셔서 채팅 주세요!

시간 있을때 답장해드릴게용

반응형

+ Recent posts