여하튼 오래 걸리는 작업이다.
Selenium보다 Pyppeteer가 빨랐지만, 결국 브라우저가 페이지의 많은 부분을 렌더링 해야만 하는 무거운 작업의 연속이었기에 해결책이 필요했다.
물론 Yahoo! Finance가 짧은 주기로 주가를 실시간 갱신해 주고, 다른 사이트는 이 정도로 신속하게 갱신해 주지 않기에 최대한 이를 활용하면서 속도를 올리고 싶었다.
하지만 너무 느린 속도를 감당할 수 없어서 갱신 주기를 포기하고 좀 더 가벼운 사이트를 찾기로 했다.
쓸만한 사이트를 찾은 것 같다
Stock Analysis라는 사이트를 발견했다.
처리 속도가 빠른 데스크탑에서 비교해도 명백히 이쪽이 빠르다.
아후는 무거운 렌더링 과정 없이 데이터를 가져올 수 없었지만 여기는 lxml
을 통해 빠르게 가져올 수 있었다.
명령어 구현
yfinance
를 쓸 수 없기 때문에 해당 종목에 대한 짜잘한 자료들에 대해선 잊기로 했다.
현재가와 종가만을 가져와서 그 등락 정도만 표시하는 것으로 결정했다.
모든 코드를 옮기기엔 꽤 길이가 있으니 한 부분만 보자
async def print_etfs(interaction, etfs_rbt, ticker):
"""Print ETF details to Discord."""
if ticker is None:
Logger.info(f"Received ETF command from {interaction.user.name}")
else:
Logger.info(f"Received ETF command for {ticker.upper()} from {interaction.user.name}")
# Initialize and defer response
await interaction.response.defer(ephemeral=False)
# Get UTC time
now_utc_aware = pytz.utc.localize(datetime.datetime.utcnow())
is_open = checker.is_nasdaq_open()
open_close = 'Open :green_circle:' if is_open else 'Close :red_circle:'
if ticker is None:
embed = create_etf_embed(now_utc_aware, open_close, is_open)
await interaction.followup.send(embed=embed)
else:
await handle_specific_ticker(interaction, ticker, now_utc_aware, etfs_rbt, is_open)
ticker
를 받지 못했으면 단순히 ETF의 리스트를 출력하게 했고, 받으면 그 종목에 대한 정보만 출력한다.
함수를 타고 흘러흘러 결과를 뽑아내게 된다.
결과는 아래와 같이 출력한다.
주변인들로부터 호평도 있었다.
쓸데없는 정보를 잘 쳐내고 필요한 거만 담았다며... 니즈를 파악한다고 하더라.
뭐 그거대로 만족한다면 되는 거 아닌가?
지금은 ETF
에 대한 얘기지만 Equity
도 매우 유사한 출력을 가지게 된다.
yfinance
가 복구되면 기존의 코드를 그대로 돌려놓아 사용할 예정.
처리부
여기도 스레딩을 활용해보기로 했다.
속도가 충분히 빠르기 때문에 큰 효용은 없을 거 같긴 하지만...
내가 사용하는 VM은 저성능 2스레드 프로세서기 때문에 꽤 괜찮을지도?
12 코어 VM을 다 사용하기 전까진 알 수가 없겠다만.
def create_etf_embed(now_utc_aware, open_close, is_open):
"""Create embed for all ETFs."""
embed = discord.Embed(title='ETF', description=f'**Market : {open_close}**', color=discord.Color.dark_blue(), timestamp=now_utc_aware)
# TEMP
nvda_data = scrape_stock_info('NVDA')
embed = add_embed_field(embed, 'NVDA', nvda_data, is_open)
embed_lock = threading.Lock()
with concurrent.futures.ThreadPoolExecutor(max_workers=3) as executor:
futures = [executor.submit(fetch_and_add_to_embed, etf, embed, is_open, embed_lock) for etf in ETFS]
for future in concurrent.futures.as_completed(futures):
try:
embed = future.result()
except Exception as e:
Logger.error(f"Exception occurred: {e}")
embed.set_footer(text="Data provided by Stock Analysis Website")
return embed
Nvidia
에 대한 정보는 임시로 출력케 했다. 어차피 자주 봐야 하니 가장 자주 쓸 명령어에 박아놨다.
스레드 세이프도 확인했으니 메모리 오염 같은 거 없이 알아서 잘 돌려줄 것이다.
애초에 오염될 껀덕지가 있나? 잘 몰라도 안전을 확인하는 것은 좋은 것이다.
큰 건 대충 정리된 듯?
C++이 아니라 Python이지만 최적화에 대한 고민은 형태는 다를 수 있으나 본질은 같은 게 아닌가?
어떻게든 응용할 수 있겠지.
'Study > Python' 카테고리의 다른 글
[Python] 스크래핑 과정 최적화를 위한 시도 (0) | 2023.10.23 |
---|---|
[Python] Aim Smoothing (0) | 2023.10.19 |
[Python] 봇 개선 및 커맨드 추가 (0) | 2023.10.16 |
[Python] 웹 파싱 / 기존 기능 개선 (0) | 2023.08.11 |
[Python] DeepL 번역 API 써보기 (0) | 2023.06.02 |