반응형
반응형

입력된 웹 페이지 내에서 모든 <img> 요소를 추출하는 프로그램을 **requests**와 BeautifulSoup 라이브러리를 사용하여 구현해 드리겠습니다. 🔎

이 방법은 웹 크롤링(Web Crawling)의 가장 기본적인 형태이며, HTML을 파싱(Parsing)하여 원하는 특정 태그를 쉽게 찾아낼 수 있습니다.

 

_image_resource_extract.py

 

import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin, urlparse
import sys

def extract_images_from_url(url):
    """
    주어진 URL의 웹 페이지에서 모든 <img> 태그의 src 속성을 추출합니다.
    
    :param url: 분석할 웹 페이지의 URL
    :return: 이미지 URL 리스트
    """
    if not (url.startswith('http://') or url.startswith('https://')):
        # 사용자가 프로토콜을 생략했을 경우 https://를 기본으로 추가
        url = 'https://' + url
        
    image_list = []
    
    print(f"URL에 접속 중: {url}")
    
    try:
        # 1. HTTP 요청 보내기
        # User-Agent를 설정하여 봇 접근이 아님을 알리고 접속 거부를 방지합니다.
        headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
        }
        response = requests.get(url, headers=headers, timeout=10)
        response.raise_for_status() # HTTP 오류가 발생하면 예외 발생
        
        # 2. HTML 파싱 (BeautifulSoup 사용)
        soup = BeautifulSoup(response.text, 'html.parser')
        
        # 3. 모든 <img> 태그 찾기
        img_tags = soup.find_all('img')
        
        # 4. 각 태그에서 src 속성 추출
        for img in img_tags:
            src = img.get('src')
            if src:
                # 5. 상대 경로를 절대 경로로 변환
                # <img src="/images/logo.png">와 같은 상대 경로를 처리하기 위해 필요합니다.
                absolute_url = urljoin(url, src)
                image_list.append(absolute_url)
                
    except requests.exceptions.RequestException as e:
        print(f"\n[오류] 웹 페이지에 접속할 수 없습니다: {e}")
        return None
    except Exception as e:
        print(f"\n[오류] 예상치 못한 오류가 발생했습니다: {e}")
        return None
        
    return image_list

if __name__ == "__main__":
    
    # 1. 사용자로부터 URL 입력 받기
    target_url = input("이미지 리스트를 추출할 웹 페이지 URL을 입력하세요 (예: google.com): ").strip()
    
    if not target_url:
        print("URL이 입력되지 않았습니다. 프로그램을 종료합니다.")
        sys.exit()

    # 2. 이미지 추출 실행
    images = extract_images_from_url(target_url)

    # 3. 결과 출력
    print("\n" + "="*50)
    
    if images is not None:
        print(f"📌 발견된 이미지 요소 개수: {len(images)}개")
        print("--- 추출된 이미지 URL 리스트 ---")
        
        # 최대 10개만 출력 (너무 길어지는 것을 방지)
        for i, img_url in enumerate(images[:10]):
            print(f"{i+1}. {img_url}")

        if len(images) > 10:
            print(f"...\n(총 {len(images)}개의 이미지 URL이 발견되었습니다.)")
    
    print("="*50)
반응형
반응형

 

[python] 유튜브 영상 경로로 다운받기 youtube_downloader.py

 

 

import yt_dlp
import os

def download_youtube_video():
    """사용자 입력 URL을 기반으로 YouTube 영상을 다운로드하는 함수"""
    
    url = input("다운로드할 YouTube 영상 URL을 입력하세요: ").strip()
    
    if not url:
        print("경고: 유효한 URL을 입력해야 합니다.")
        return

    # 📌 수정 1: 다운로드 폴더 경로 설정 
    current_dir = os.getcwd() # 현재 스크립트가 실행되는 디렉토리
    download_dir = os.path.join(current_dir, 'downloads') # 'downloads' 하위 폴더 경로 생성
    
    # 📌 수정 2: 'downloads' 폴더가 없으면 생성
    if not os.path.exists(download_dir):
        os.makedirs(download_dir)
        print(f"[알림] 'downloads' 폴더를 생성했습니다: {download_dir}")

    # 2. 다운로드 옵션 설정
    ydl_opts = {
        #'format': 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/best[ext=mp4]/best', 
        'format': 'bestvideo+bestaudio/best',
        
        # 📌 수정 3: outtmpl 옵션에 'download_dir' 경로 추가
        # outtmpl 옵션: 저장될 파일의 템플릿 (경로 포함)
        'outtmpl': os.path.join(download_dir, '%(title)s.%(ext)s'), 
        
        'postprocessors': [{
            'key': 'FFmpegMetadata',
            'add_metadata': True,
        }],
    }

    # 3. 다운로드 실행
    try:
        print(f"\n[알림] 다운로드를 시작합니다: {url}")
        
        with yt_dlp.YoutubeDL(ydl_opts) as ydl:
            ydl.download([url])
            
        print("\n🎉 다운로드가 성공적으로 완료되었습니다!")
        print(f"저장된 위치: {download_dir}")
        
    except yt_dlp.utils.DownloadError as e:
        print(f"\n[오류] 다운로드 중 오류가 발생했습니다: {e}")
    except Exception as e:
        print(f"\n[오류] 예상치 못한 오류가 발생했습니다: {e}")


if __name__ == "__main__":
    download_youtube_video()
반응형
반응형

랜덤 워크(Random Walk)를 사용하여 **아트적인 노이즈 트레일(Artistic Noise Trail)**을 만드는 것은 제너레이티브 아트(Generative Art)에서 매우 흔하고 흥미로운 기법입니다. 이는 각 단계에서 **무작위성(Stochasticity)**을 이용해 경로를 결정함으로써 예측 불가능하면서도 유기적인 움직임을 만들어냅니다.

 

파이썬에서는 주로 turtle 또는 **matplotlib**을 사용하여 시각화할 수 있지만, 여기서는 제너레이티브 아트에 자주 사용되는 접근 방식인 랜덤 증분을 이용해 구현해 보겠습니다.

 

"""
랜덤 워크(Random Walk)를 사용하여 **아트적인 노이즈 트레일(Artistic Noise Trail)**을 만드는 것은 제너레이티브 아트(Generative Art)에서 매우 흔하고 흥미로운 기법입니다. 이는 각 단계에서 **무작위성(Stochasticity)**을 이용해 경로를 결정함으로써 예측 불가능하면서도 유기적인 움직임을 만들어냅니다.

파이썬에서는 주로 turtle 또는 **matplotlib**을 사용하여 시각화할 수 있지만, 여기서는 제너레이티브 아트에 자주 사용되는 접근 방식인 랜덤 증분을 이용해 구현해 보겠습니다.

"""


import numpy as np
import matplotlib.pyplot as plt

def generate_random_walk_trail(steps, noise_strength=1):
    """
    주어진 단계 수만큼 랜덤 워크 트레일 데이터를 생성합니다.
    
    :param steps: 랜덤 워크를 진행할 단계 수
    :param noise_strength: 노이즈/이동 강도 (클수록 경로가 거칠어짐)
    :return: x, y 좌표 배열
    """
    # 각 단계에서의 x, y 변화량 (랜덤 증분)을 생성합니다.
    # -noise_strength부터 +noise_strength 사이의 균일 분포 난수
    dx = np.random.uniform(-noise_strength, noise_strength, steps)
    dy = np.random.uniform(-noise_strength, noise_strength, steps)

    # 누적합을 계산하여 경로(트레일)를 만듭니다.
    # 각 지점은 이전 지점에서의 변화량을 누적한 결과입니다.
    x_trail = np.cumsum(dx)
    y_trail = np.cumsum(dy)
    
    return x_trail, y_trail

# --- 시각화 설정 ---
STEPS = 5000  # 경로 길이
NOISE_LEVEL = 1.5 # 노이즈 강도 조절

x_coords, y_coords = generate_random_walk_trail(STEPS, NOISE_LEVEL)

# Matplotlib으로 트레일 시각화
fig, ax = plt.subplots(figsize=(10, 10))
ax.plot(x_coords, y_coords, 
        color='white',      # 선 색상
        linewidth=0.5,      # 선 두께
        alpha=0.8)          # 투명도

# 배경 및 축 설정
ax.set_facecolor('black')
ax.set_xticks([])
ax.set_yticks([])
ax.set_title(f"Random Walk Artistic Noise Trail ({STEPS} steps)", color='white')

# 축 비율을 같게 설정하여 왜곡 방지
ax.set_aspect('equal', adjustable='box')

plt.show()

 

 

 

 

import numpy as np
import matplotlib.pyplot as plt

steps = np.random.choice([1, -1], size=(2,1000))
pos = np.cumsum(steps, axis=1)
plt.plot(pos[0], pos[1], color='lime')
plt.axis('off')
plt.title("Random walk path", color='green')
plt.show()

 

반응형
반응형

turtle 로 전체화면에서 임의로 선그리기 

 

import turtle
import random

# 화면 설정
def setup_screen():
    """창을 설정하고 전체 화면과 유사하게 최대화합니다."""
    screen = turtle.Screen()
    screen.setup(width=1.0, height=1.0) # 화면 크기를 최대화합니다.
    screen.title("무작위 선 그리기 (전체 화면)")
    screen.colormode(255) # RGB 색상 모드를 0-255로 설정합니다.
    screen.bgcolor("black") # 배경색을 검은색으로 설정합니다.
    screen.tracer(0) # 그리기 속도를 높이기 위해 자동 화면 업데이트를 끕니다.
    return screen

# 거북이 설정
def setup_turtle():
    """선을 그릴 거북이를 설정합니다."""
    t = turtle.Turtle()
    t.hideturtle() # 거북이 아이콘을 숨깁니다.
    t.speed(0) # 최고 속도로 설정합니다.
    t.pensize(2) # 펜 두께를 설정합니다.
    return t

# 무작위 색상 생성
def get_random_color():
    """무작위 RGB 색상 튜플을 반환합니다."""
    r = random.randint(0, 255)
    g = random.randint(0, 255)
    b = random.randint(0, 255)
    return (r, g, b)

# 메인 그리기 루프
def draw_random_lines(t, screen):
    """화면이 종료될 때까지 무작위 선을 계속 그립니다."""
    while True:
        # 무작위 색상 및 위치 설정
        color = get_random_color()
        t.pencolor(color)
        
        # 펜을 든 상태로 무작위 위치로 이동 (현재 위치에서 그리기 시작)
        t.left(random.randint(-180, 180)) # 무작위로 방향을 돌립니다.
        
        # 무작위 길이만큼 앞으로 이동 (선을 그림)
        distance = random.randint(50, 300)
        t.forward(distance)

        # 화면 가장자리를 벗어났는지 확인하고, 벗어났다면 펜을 들고 중앙 근처로 이동
        # 이 과정이 없으면 거북이가 화면 밖으로 나가버려 그림이 멈춘 것처럼 보일 수 있습니다.
        current_x, current_y = t.position()
        screen_width = screen.window_width()
        screen_height = screen.window_height()
        
        if abs(current_x) > screen_width / 2 or abs(current_y) > screen_height / 2:
            t.penup() # 펜 들기
            t.goto(0, 0) # 중앙으로 이동
            t.left(random.randint(-180, 180)) # 방향을 다시 무작위로 설정
            t.pendown() # 펜 내리기
            
        # 화면 업데이트 (tracer(0)를 사용했으므로 수동으로 업데이트)
        screen.update()

# 프로그램 실행
if __name__ == "__main__":
    screen = setup_screen()
    t = setup_turtle()
    
    try:
        draw_random_lines(t, screen)
    except turtle.Terminator:
        # 창 닫기 버튼을 눌렀을 때 발생하는 예외 처리
        print("프로그램이 종료되었습니다.")
    except Exception as e:
        print(f"예외 발생: {e}")
        
    # 창을 닫을 때까지 프로그램이 대기하도록 함 (실제 draw_random_lines 루프에서는 필요 없음)
    # turtle.done()
반응형
반응형

 

[python] asciichartpy -  터미널(콘솔) 환경에 깔끔하고 읽기 쉬운 텍스트 기반의 ASCII 아트 그래프를 그려주는 라이브러리

 

pip install asciichartpy

 

https://pypi.org/project/asciichartpy/

 

Client Challenge

JavaScript is disabled in your browser. Please enable JavaScript to proceed. A required part of this site couldn’t load. This may be due to a browser extension, network issues, or browser settings. Please check your connection, disable any ad blockers, o

pypi.org

 

 

import asciichartpy 

data = [1, 2, 3, 4, 3, 2, 1, 0, 1, 2, 3, 4, 5, 4, 3, 2, 1]
print("ASCll Line Chart Example")
print(asciichartpy.plot(data, {'height': 10}))

 

import asciichartpy as ac

series1 = [20, 25, 22, 28, 30, 24, 35, 32, 26]
series2 = [10, 15, 12, 18, 20, 14, 25, 22, 16]

# 두 개의 계열을 하나의 차트에 표시
print(ac.plot([series1, series2], {'height': 15, 'colors': [ac.red, ac.blue]}))
반응형
반응형

Plotly를 사용한 게이지 차트 (Gauge Chart) 생성 예제 (Python Code)

 

Plotly Tutorial - 파이썬 시각화의 끝판왕 마스터하기 https://wikidocs.net/book/8909

 

https://plotly.com/python-api-reference/plotly.graph_objects.html

 

plotly.graph_objects: low-level interface to figures, traces and layout — 6.3.0 documentation

plotly.graph_objects: low-level interface to figures, traces and layout plotly.graph_objects contains the building blocks of plotly Figure: traces (Scatter, Bar, …) and Layout >>> import plotly.graph_objects as go Figure Figure([data, layout, frames, 

plotly.com

Plotly는 인터렉티브한 시각화가 가능한 파이썬 그래픽 라이브러리 입니다. 기본적인 시각화부터 통계, 재무, 지리 과학 및 3-dimensional 을 포함한 40개 이상의 차트 타입을 제공하는 오픈소스 입니다. 기본적으로 쥬피터 노트북에 시각화가 가능하며 인터렉티브한 dashboards 위해 Dash 또는 Chart Studio와 같은 라이브러리와 통합 및 확장이 가능합니다.

 

특징

  1. Interactive 한 시각화 가능하여 사용자가 시각화된 그래프를 쉽게 줌인, 줌아웃 및 툴팁을 활용한 데이터확인이 가능합니다. (Matplotlib/Seaborn 과의 가장 큰 차이점)
  2. Dash, 및 chart Studio 와같은 visualisation tools 연동으로 Web 및 application 통해 확인이 가능합니다.
  3. matplotlib 대비 코드가 훨씬 간편합니다.(이 책을 통해 익숙해진다면..)
  4. Python 뿐만 아니라 R, Julia, MATLAB 등과 같은 다른 프로그래밍 언어를 스크립트를 사용하여 이용이 가능합니다.
  5. Plotly는 기본적으로 JSON(JavaScript Object Notation) 형태를 주고받는 구조로 되어있습니다. 하지만 걱정 하실필요 없습니다. 본 책에서는 복잡한 JSON 형태가 아닌 직관적인 객체를 사용하는 방법으로 진행할 예정입니다.
  6. Matplotlib 차트를 Plotly 차트로 변화나는 기능이 지원됩니다.
  7. Pandas와의 호환 기능이 추가되어 판다스 plotting 백엔드에 Plotly를 설정하면 Padas 데이터프레임에서 바로 Plotly 로 시각화가 가능합니다.
  8. 기본적인 색감이 매우 이쁩니다.(개인적인 취향)
  9. 라이센스가 무료 입니다.

 

 

 

"""
    pip install plotly
    Plotly를 사용한 게이지 차트 (Gauge Chart) 생성 예제 (Python Code)
"""

import plotly.graph_objects as go
import plotly.offline as pyo

# --- 게이지 차트 데이터 설정 ---
value = 75  # 현재 값 (예: 판매 목표 달성률 75%)
max_value = 100 # 최대 값
title_text = "판매 목표 달성률"
unit_text = "%"

# --- Plotly Indicator 객체 생성 ---
fig = go.Figure(go.Indicator(
    mode = "gauge+number+delta", # 게이지, 숫자, 델타(변화량)를 표시
    value = value,
    number = {'suffix': unit_text}, # 숫자 뒤에 단위 표시
    domain = {'x': [0, 1], 'y': [0, 1]},
    title = {'text': title_text, 'font': {'size': 24}},
    
    # --- 게이지 설정 ---
    gauge = {
        'shape': "angular", # 게이지 모양 (angular: 원형, bullet: 수평 막대)
        'axis': {'range': [None, max_value], 'tickwidth': 1, 'tickcolor': "darkblue"},
        'bar': {'color': "darkblue"}, # 현재 값 막대의 색상
        'bgcolor': "white",
        'borderwidth': 2,
        'bordercolor': "gray",
        
        # --- 구간별 색상 설정 (Thresholds) ---
        'steps': [
            {'range': [0, 50], 'color': "lightgray"},   # 0% ~ 50%
            {'range': [50, 85], 'color': "lightblue"},  # 50% ~ 85%
            {'range': [85, 100], 'color': "yellowgreen"} # 85% ~ 100% (목표 근접/달성)
        ],
        
        # --- 목표선 설정 (Threshold) ---
        'threshold': {
            'line': {'color': "red", 'width': 4},
            'thickness': 0.75, # 목표선의 두께
            'value': 90 # 목표 값 (예: 90%)
        }
    }
))

# --- 레이아웃 설정 ---
fig.update_layout(
    paper_bgcolor = "white", # 배경 색상
    font = {'color': "black", 'family': "Arial"},
    margin = dict(l=20, r=20, t=50, b=20) # 여백 설정
)

# --- 차트 출력 (브라우저에서 확인) ---
# pyo.plot(fig, filename='gauge_chart.html')

# --- (선택 사항) Notebook 환경에서 출력 ---
fig.show()
반응형

+ Recent posts