반응형

 

1. BeautifulSoup

 

BeautifulSoup 라이브러리에서는 웹사이트에 데이터를 읽어와서 파싱할 수 있는 기능을 제공하고 있다.

import requests
from bs4 import BeautifulSoup

def get_fear_and_greed():
    url = "https://edition.cnn.com/markets/fear-and-greed"
    response = requests.get(url)
    soup = BeautifulSoup(response.text, 'html.parser')
    
    # HTML 구조에 맞는 특정 요소를 찾아 Fear and Greed Index 값을 추출
    index = soup.find("div", class_="fear-and-greed-index").text.strip()
    return index

if __name__ == "__main__":
    index_value = get_fear_and_greed()
    print(f"CNN Fear and Greed Index: {index_value}")

 

 

하지만 아래 코드를 수행해보면 정상적으로 데이터를 파싱하지 못하는 것 처럼 보일 것이다.

(특히 직접 원하는 영역의 div의 class이름을 검색해보면 결과가 포함이 되지 않을 것이다.)

 

2. Selenium

그 이유는 해당 값이 JavaScript로 동적으로 로딩되기 때문이다. requests와 BeautifulSoup은 HTML 소스를 바로 가져오기 때문에 JavaScript로 생성된 콘텐츠는 포함되지 않는다.

 

이 문제를 해결하려면, Selenium과 같은 브라우저 자동화 도구를 사용하여 동적으로 로딩되는 콘텐츠를 포함한 페이지를 가져올 수 있다. Selenium을 사용하면 JavaScript가 로드된 후 페이지에서 데이터를 추출할 수 있다.

 

from selenium import webdriver
from selenium.webdriver.common.by import By

url = "https://edition.cnn.com/markets/fear-and-greed"

# 브라우저를 실행합니다.
driver = webdriver.Chrome()

driver.get(url)

# 원하는 div를 찾습니다.
index_value = driver.find_element(By.CLASS_NAME, "market-fng-gauge__dial-number").text
print(f"CNN Fear and Greed Index: {index_value}")

# 브라우저 종료
driver.quit()

 

 

이때 매 실행마다 url에 해당하는 사이트가 열리고 켜지면서 실행시간이 아주 오래 걸리는 것을 확인할 수 있다.

 

3. 시간 단축

실제로 데이터를 동적로딩해야하기 때문에 이는 어쩔 수 없는 방법이다. 하지만 시간 단축을 위해서 몇가지 추가할 수 있는 옵션이 있다.

 

Seleniumheadless 모드를 사용해 브라우저 창을 열지 않고 백그라운드에서 동작하도록 할 수 있다. 이렇게 하면 화면에 표시되는 부분을 렌더링하지 않아서 속도가 빨라진다.

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options

url = "https://edition.cnn.com/markets/fear-and-greed"

# Chrome 옵션 설정 (headless 모드)
chrome_options = Options()
chrome_options.add_argument("--headless")  # 화면을 표시하지 않음

# 브라우저를 headless 모드로 실행
driver = webdriver.Chrome(options=chrome_options)

driver.get(url)

# 원하는 div를 찾습니다.
index_value = driver.find_element(By.CLASS_NAME, "market-fng-gauge__dial-number").text
print(f"CNN Fear and Greed Index: {index_value}")

# 브라우저 종료
driver.quit()

 

 

4. api를 활용하자

그렇지만 실제로 동적으로 데이터를 받아와야 하는 입장이기 때문에 속도저하는 불가피하다.

이를 개선하기 위해서 다양한 api를 활용해야한다.

 

만약에 미국 주식 지수와 관련한 데이터라면 yfinance 라이브러리를 통해서 데이터를 제공받을 수 있다.

pip install yfinance

 

기본 예시 코드

import yfinance as yf

# VIX 지수 티커
vix = yf.Ticker("^VIX")

# 최근 종가 데이터 가져오기
vix_data = vix.history(period="1d")
print("VIX 지수:", vix_data["Close"].iloc[-1])

 

 

웹크롤링과 라이브러리를 함께 사용한 예시 코드

import sys
import requests
import yfinance as yf
import matplotlib.pyplot as plt
from PyQt6.QtWidgets import QApplication, QWidget, QVBoxLayout, QLabel
from PyQt6.QtCore import Qt
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.options import Options
from matplotlib.backends.backend_qtagg import FigureCanvasQTAgg as FigureCanvas

class DataFetcher:
    """데이터를 가져오는 클래스 (웹 크롤링 또는 API)"""

    @staticmethod
    def fetch_fear_greed_index():
        """CNN Fear & Greed Index 크롤링"""
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--ignore-certificate-errors")

        driver = webdriver.Chrome(options=chrome_options)
        driver.get("https://edition.cnn.com/markets/fear-and-greed")

        index_value = driver.find_element(By.CLASS_NAME, "market-fng-gauge__dial-number").text
        driver.quit()

        return f"CNN Fear & Greed Index: {index_value}"

    @staticmethod
    def fetch_vix_data():
        """VIX 지수 데이터 가져오기 (지난 1개월)"""
        vix = yf.Ticker("^VIX")
        vix_data = vix.history(period="1mo")
        return vix_data

class MarketIndexApp(QWidget):
    """GUI를 관리하는 클래스"""

    def __init__(self):
        super().__init__()
        self.setWindowTitle("Market Index Dashboard")
        self.resize(500, 400)

        self.layout = QVBoxLayout()
        
        self.fear_greed_label = QLabel("Loading Fear & Greed Index...", self)
        self.fear_greed_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.layout.addWidget(self.fear_greed_label)

        self.vix_label = QLabel("Loading VIX Index...", self)
        self.vix_label.setAlignment(Qt.AlignmentFlag.AlignCenter)
        self.layout.addWidget(self.vix_label)

        # 그래프 추가
        self.figure, self.ax = plt.subplots(figsize=(5, 3))
        self.canvas = FigureCanvas(self.figure)
        self.layout.addWidget(self.canvas)

        self.setLayout(self.layout)

        self.update_data()

    def update_data(self):
        """데이터를 가져와 UI에 표시"""
        self.fear_greed_label.setText(DataFetcher.fetch_fear_greed_index())

        vix_data = DataFetcher.fetch_vix_data()
        self.vix_label.setText(f"VIX 지수 (최신값): {vix_data['Close'].iloc[-1]:.2f}")

        # 그래프 업데이트
        self.ax.clear()
        self.ax.plot(vix_data.index, vix_data["Close"], marker='o', linestyle='-', color='b', label="VIX Close")
        self.ax.set_title("VIX Index Trend (Last 1 Month)")
        self.ax.set_xlabel("Date")
        self.ax.set_ylabel("VIX Value")
        self.ax.legend()
        self.ax.grid(True)

        self.canvas.draw()

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MarketIndexApp()
    window.show()
    sys.exit(app.exec())
반응형
반응형

 

사실 chat gpt 에게 물어보면서 진행하면 더 편하지만, 작업 환경 셋팅을 위한 전반적인 그림이 필요하신 분이 있을 것 같아 글을 남깁니다. ㅎㅎ

 

 

1. python 설치 

 

직접 python 사이트에서 설치해도 되지만, 윈도우 작업 환경이시라면, MS store에서 python을 설치하는 것 만으로 

python 설치 & 환경변수 설정이 한번에 가능합니다.

 

 

여러가지 python 버전이 있는데, 그냥 아무거나 설치하셔도 됩니다.

사용하실 대부분의 기능들은 python3이상이라면 정상 동작 할 것이기 때문에...

 

 

2. VS code 설치 

 

아래 사이트에서 vsc 코드를 다운 받으시고 실행시키면 됩니다.

https://code.visualstudio.com/download

 

Download Visual Studio Code - Mac, Linux, Windows

Visual Studio Code is free and available on your favorite platform - Linux, macOS, and Windows. Download Visual Studio Code to experience a redefined code editor, optimized for building and debugging modern web and cloud applications.

code.visualstudio.com

 

 

vsc에서 python 개발을 위한 플러그인을 설치해야하는데, 아래처럼 python extensions을 설치해주시면 됩니다. 

 

 

3. 가상 환경 설정 

 

작업할 test.py 파일 하나 만드시고 terminal에 가상환경 생성을 위한 명령어를 입력

python -m venv venv  # 가상환경 생성

 

 

그리고 가상환경 활성화를 위해서 아래 명령어를 입력

source venv/bin/activate  # (Mac/Linux) 활성화
venv\Scripts\activate  # (Windows) 활성화

 

간혹 아래 처럼 문제가 발생하는 경우가 있다.

 

단순히 power shell이 관리자 권한이 아니기에 발생하는 문제이기 때문에 아래 명령어를 입력하여 관리자 권한의 terminal로 변경해주면 된다.

 

 Set-ExecutionPolicy Unrestricted -Scope Process

 

 

그러면 아래 사진 처럼 teminal command 창 옆에 (venv)이라고 가상환경이 활성화 된 것을 확인할 수 있다.

 

 

4. PyQt 및 필수 패키지 설치

 

 

pip install PyQt6 pyqt6-tools


PyQt6: PyQt 프레임워크
pyqt6-tools: Qt Designer, uic(코드 변환기) 등 포함

 

5. 코드 작성

 

아래 처럼 기본 코드를 작성

Run - start debuging을 수행하면 창 하나가 나온다.

import sys
from PyQt6.QtWidgets import QApplication, QWidget

class MyApp(QWidget):
    def __init__(self):
        super().__init__()
        self.init_ui()

    def init_ui(self):
        self.setWindowTitle("My PyQt App")  # 창 제목 설정
        self.resize(400, 300)  # 창 크기 설정 (가로x세로)
        self.show()  # 창 표시

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApp()
    sys.exit(app.exec())  # 앱 실행

 

 

 

6. 사실 ui 작업이 많아지면 gt designer를 통해서 ui를 만드는게 효율적입니다.

https://jeongbang.tistory.com/3

 

VSCode 에서 PyQt5를 이용한 GUI 만들기

PyQt5를 이용해 파이썬 GUI 프로그래밍을 해보도록 하겠습니다. 파이썬 개발환경이 구성되어 있다는 가정하에 진행하도록 하겠습니다. VSCode에서 Python 개발환경 구성하기 파이썬 IDE에는 여러가지

jeongbang.tistory.com

 

반응형
반응형

 

 


노티드에서 크림 소금빵 이후 신메뉴가 뜸했는데, 마리토쪼라는 신메뉴가 등장했습니다. 

 

마리토쪼? 마리토조? 그게 뭔데...?

 

 

요새 일본에서 대유행인 빵이라고 합니다. 이탈리아의 전통 디저트로, 버터, 설탕, 계란이 많이 사용된 '브리오슈' 라는 빵에 생크림을 듬뿍발라 끼운 것이라고 합니다. 생크림에 견과류나 말린 건포도 같은 것들이 포함되기도 한다고 합니다.

 

 

 

비주얼만 봐도 존맛인데요..?

 

 

 

 

노티드 덕후로서 참지 못하고 바로 구매 완료 : )

 

노티드 인스타 피드에 나와있는 것 처럼 총 6가지 마리토쪼 메뉴가 추가됐습니다.

 

https://www.instagram.com/cafeknotted/

 

 

 

 

역대급 비주얼인데요??..

 

 

실물도 진짜 저럴까요???

저는 메론맛 마리토쪼, 귤 유자맛 마리토쪼 2개를 구입했습니다. 개당 소금빵과 동일한 5200원(24.08.11기준)

 

 

 

 

 

이 정도면 비쥬얼도 합격이네요.

안에 크림도 잔뜩 들어있습니다.

 

 

가장 중요한 맛은....

 

대존맛입니다. 기존에 노티드 크림 소금빵은 크림 도넛에서 사용하던 크림들과 동일한 크림을 사용했다면, 마리토쪼에 들어가는 크림은 맛이 전혀 다른 생크림을 사용하고 있었습니다.

 

 

유자맛 마리토쪼에는 그냥 생크림이 아니라 유자가루같은게 들어가 있어서 상큼한 맛이 났고, 멜론 마리토쪼에는 메론향이 잔뜩 나는 생크림가 멜론맛 커스터드 크림이 들어있었습니다. 

 

 

결론은 대만족!!

 

 

두 제품중에서는 저는 멜론맛 마리토쪼를 강추합니다. 깊은 멜론맛과 향이 잔뜩 느껴집니다. 

크림이 잔뜩 들어있고, 기존에 노티드 도넛과는 차별화되게 다양한 크림, 과일을 사용한다는 점이 인상적이었습니다. 

 

단점은 딱히 없지만 굳이 말하자면, 빵이 생각했던 것 보다 푹신푹신한 느낌은 아니였고, 그냥 일반적인 빵느낌이었던거 같아요.

 

제 기준 종합 평점은

 

맛 : ★ ★ ★ ★☆

비주얼 : ★ ★ ★ ★ ★  

가격 : ★ ★ ★ ★ ☆

 

꼭 한번 드셔보시길 강추드립니다.

반응형
반응형

[산호맨숀 본점 프로필 사진 촬영 후기]


안녕하세요!

산호맨숀에서 프로필 사진을 촬영해서 후기를 남기려고 합니다.

 

저번에 시현하다를 다녀오고 프로필 사진을 찍는데 재미가 들려서, 이번에는 시현하다 만큼 유명한 산호맨숀에 다녀왔습니다.

https://gusdnr69.tistory.com/299

 

시현하다 솔직 후기 :: 시현하다 모먼트 본점

[시현하다 강남 본점 프로필 사진 촬영 후기] (현영 작가님 촬영) 안녕하세요! 며칠 전에 시현하다 강남 본점에서 프로필 사진을 촬영해서 후기를 남기려고 합니다. 갤러리를 뒤져보는데 제 사진

gusdnr69.tistory.com

 

2022년 기준 가격표

산호맨숀은 시현하다와는 다르게 지점이 딱 2군데 밖에 없습니다. 을지로에 세운상가에 있는 본점과 이태원에 있는 경리단점입니다. 그리고 사진 작가님이 여러분이 아니라 한 분씩 밖에 없다보니 시현하다와는 다르게 예약이 되게 어려웠습니다..

 

 

예약은 매월 1일 점심 12시에 산호맨숀 오프카톡을 통해서만 예약이 가능합니다.

(네이버 예약안되요)

이런식으로 카톡을 보내놓게 되면 순서에 맞춰서 타임을 배정해주십니다.

예약시간은 위 사진 참고!

 

 

을지로점 위치는 세운전자상가입니다. 

 

전자상가 입구가 되게 여러군데 다 보니 정문 쪽으로 들어가는 것을 추천합니다.

엘리베이터 타고 7층에 도착하면 바로 보입니다. 

 

한 10분전 부터 입장가능합니다. 미리 도착하면 카톡으로 도착했다고 말씀드리고 앞에서 기다리면 됩니다!

 

대기실에서 간단하게 정리할 수 있고, 준비가 되면은 촬영에 들어갑니다.

 

포토존들도 있고, 촬영 공간은 포토존 안쪽으로 들어오면 있습니다.

 

 

 

 

 

 

 

이후에 작가님을 만나서 짧은 상담을 진행했습니다.

어떤 색을 사용하고 싶은지, 측면 사진을 원하는지, 정면을 원하는지 등을 말씀드릴 수 있습니다.

물론 정면 사진만 찍는게 아니고, 측면 사진들도 찍어주시고, 여러각도의 사진들 중에서 한장을 선택할 수 있게끔 도와주십니다.

 

작가님, 직원분들 굉장히 친절하셨고, 편안한 분위기에서 진행되어서 좋았습니다. 

여러 후기들을 보니까 

 

1) "추가컷을 부추긴다." 라는 의견들이 있더라구요.  

우선 저는 추가 컷을 부추기는 건 전혀 없었습니다. 추가금을 내면 사진 장수를 더 가져갈 수 있다는 안내만 해주셨고, 전혀 부추기거나 강요하지 않으셨습니다. 되게 클린했어요.

 

2) "너무 서두르는 분위기"이다.

이거는 너무 당연한거 아닌가 싶습니다.. 30분이라는 시간안에 촬영, 포토샵까지 전부 진행되어야 하기에, 빠르게 진행하는게 당연하다고 생각합니다. 저는 오히려 빠르게 빠르게 진행해주셔서 좋았습니다. 

 

 

 

제가 생각하는 산호맨숀의 장점은 시현하다보다 훨씬 촬영시간이 길다는 것입니다. 5분정도는 촬영에 시간을 할애해주십니다. (기존 시현하다에서는 거의 1분만에 끝나버려 아쉬웠습니다.) 길게 촬영을 진행해주시다 보니 다양한 구도에서 사진 촬영을 해주시고, 최종본을 고를 때 선택의 폭이 다양해서 그부분이 되게 마음에 들었습니다!

 

저는 이번에는 정면 정색(?) 사진을 찍고 싶어서 정면 진지 사진으로 골랐습니다. 

 

 

촬영이후에는 빠르고 정확하게 작가님이 포토샵을 진행해주십니다.

정말 새로 빚어주시더라구요.. ㅎㅎㅋㅋㅋㅋ 어디 올리기 민망한 정도입니다. ㅎㅎ

저는 개인적으로 매우 만족합니다! (시현하다 때보다)

 

 

포토존에서 한장

 

최종 결과물입니다. 

사진이 나오면 아래처럼 포토존에서 작가님이 직접 사진 촬영을 도와주십니다. 

 

결과물 되게 만족하구, 다음에는 조금더 과감한 사진으로 다시 찍어보고 싶어요. 

프로필사진을 찍어볼까 고민중이시라면, 산호맨숀 강추드립니다.

 

궁금한 점 댓글남겨주시면 확인하는 대로 답변드리겠습니다. ㅎㅎ

반응형
반응형
#include <iostream>
using namespace std;

int n, q;
int arr[500001] = { 0, };
int qarr[500001] = { 0, };


int binarysearch(int v, int s, int e) { // recursion 

	//1.base condition
	if (s > e)
		return -1;

	//2.divide
	int m = (s + e) / 2;

	if (v == arr[m]) return m;
	else if (v > arr[m]) return binarysearch(v, m + 1, e);
	else return binarysearch(v, s, m - 1);

}



int binarysearch2(int v, int s, int e) { // while 

	int start_val = s;
	int end_val = e;

	while (start_val <= end_val) {
		int m = (start_val + end_val) / 2;
		if (v == arr[m]) return m;
		else if (v > arr[m]) start_val = m + 1;
		else end_val = m - 1;
	}

	return -1;
}

int main() {

	cin >> n;
	for (int i = 0; i < n; i++)
		cin >> arr[i];
	cin >> q;
	for (int i = 0; i < q; i++)
		cin >> qarr[i];


	for (int i = 0; i < q; i++) {
		int val = binarysearch(qarr[i],0,n-1);
		cout << val;
		if (i != (q - 1))
			cout << ' ';
	}
	cout << endl;

	return 0;
}
반응형
반응형
#include <stdio.h>
#define MAXSIZE 100000

const int LM = (int)100001;
int index[LM], temp[LM];

void mergesort(int s, int e, int* a, int* b) {

    //1. base condition
    if (s >= e)
        return;

    //2.divide
    int mid = (s + e) / 2;
    

    //3. conquer
    mergesort(s, mid, a, b);
    mergesort(mid + 1, e, a, b);

    //4. merge
    int i = s, j = mid + 1;
    for (int k = s; k <= e; k++) {

        if (i > mid)
            b[k] = a[j++];
        else if (j > e)
            b[k] = a[i++];
        else if (a[i] > a[j])
            b[k] = a[j++];
        else
            b[k] = a[i++];
    }

    //5. copy
    for (int k = s; k <= e; k++) {
        a[k] = b[k];
    }
}
반응형
반응형

범계역 수제버거 맛집 슬렘덩크 버거는 범계역 2번출구 입구쪽에 위치해 있습니다.

지하 1층에 있으니 참고 ㅎㅎ

 

 

대표메뉴는 덩크 치킨버거랑 저스트 치즈버거!

 

덩크치킨버거(8400)

미국식 치킨샌드워치 느낌인데, 패티도 크고 두툼하고 개인적으로는 굉장히 호

 

저스트 치즈버거(7400)

근본 소고기 패티에 체다치즈가 들어가있는 베스트 메뉴 

 

 

 

가게 외관은 굉장히 힙하게 되어있습니다.

농구관련 소품들로 예쁘게 꾸며져 있습니다.

그리고 힙한 외국 음악들이 bgm으로 흘러나옵니다.

 

분위기는 대만족

저는 저스트 치즈버거세트(12900)를 먹어보았습니다. 

 

개인적인 후기는...

 

우선 수제버거고 굉장히 맛있다!!

번도 일반 프렌차이즈에서  파는것보다 훨씬 맛있습니다.

 

전반적으로 꽤나 맛있어서, 수제버거집이 없는 범계에 가뭄의 단비같은 느낌 ㅠㅠ

 

 

 

다만 패티는 개인적으로 좀 아쉬웠습니다.

소고기패티같은 경우에는 다른 수제버거 패티들에 비해서 좀 얇다는 생각이 들었습니다. 패티를 누르면서 구운것도 있지만, 그걸 감안해도 육향은 좀 적은 느낌 ㅠㅠ 

 

개인적으로 세트 가격이라면, 쉑쉑 더블패티 + 음료를 먹을것 같지만, 그래도 범계에서 이만한 수제버거집은 없다고 생각이 들더라구요!

 

 

안 가보신 분들이라면, 한번쯤 가보시기를 추천드려요!

 

 

 

 

 

반응형
반응형

요새 너무나도 핫한 밀도식빵을 먹어보았습니다 : )

대표메뉴인 밀도식빵이외에도 다양한 빵들이 있지만, 대표메뉴는 

 

담백식빵(5500)

물 대신 무지방 우유와 청정 유기농 밀가루로 만든 담백하고 쫄깃한 식빵

 

리치식빵(5800)

생크림이 듬뿍 들어가 유지방 특유의 고소하고 부드러운 맛이 나는 식빵

 

 

이 두가지!

 

저는 리치식빵을 먹어봤습니다.

지점에 따라 1.8cm/2.5cm 선택해서 원하는 두께로 커팅 해주는데 2.5cm를 선택!

 

 

먹어본 솔직 후기는 "맛있는 식빵"이다.

생크림을 사용해서 만들어서 그런지 확실히 빵자체에서 버터와 생크림의 풍미가 강하게 느껴졌습니다.

고소하고 굉장히 담백하다는 느낌을 받았습니다.

 

일반 프렌차이즈 식빵의 경우에는 옆 꼬다리 부분이 딱딱하고 맛없는 경우가 많은데,

신기하게도 밀도 식빵은 꼬다리부분도 식빵안쪽이랑 식감차이가 크지않고 부드러웠어요.

 

평소에 식빵을 좋아하지 않는데도 맛있게 먹을 수 있었습니다.

빵을 좋아하시는 분들은 참 좋아할 수 있겠다고 생각했지만, 제가 먹기에는 그래봤자 "식빵은 식빵이다." 

맛있게 잘 만든 식빵이고, 단백하고 깔끔하지만, 솔직히 그냥 맛있는 식빵이더라구요.. ㅋㅋㅋㅋ( 당연한 말이지만ㅎㅎ)

 

경험삼아 먹어보는거는 강추! 근데 저는 굳이 빵만 먹으려고 지점에 재방문해서 구매하지는 않을 것 같습니다. 

밀도에서 준 딸기 잼도 함께 먹어보았습니다. 

방부제나 응고제를 넣지 않고 만든 잼이라고 하는데 사실 잼은 큰 차이점을 모르겠더라구요. ㅎㅎ

 

결론

1. 맛있다.

2. 식빵이다.

 

반응형

+ Recent posts