Guidelines

Yahoo Financeμ—μ„œ 주식 데이터λ₯Ό μ‹€μ‹œκ°„μœΌλ‘œ μˆ˜μ§‘ν•˜κΈ°

μ‹œμ‹œκ°κ° λ³€ν•˜λŠ” 주식 μ‹œμž₯! μ‹€μ‹œκ°„μœΌλ‘œ 주식 데이터λ₯Ό μˆ˜μ§‘ν•΄ 주기적으둜 μ €μž₯ν•˜κ³  μ‹Άλ‹€λ©΄ μ–΄λ–»κ²Œ ν•΄μ•Ό ν• κΉŒμš”?

이번 μˆ˜μ—…μ—μ„œλŠ” Selenium을 ν™œμš©ν•˜μ—¬ Yahoo Financeμ—μ„œ 주식 데이터λ₯Ό λ™μ μœΌλ‘œ μΆ”μΆœν•˜λŠ” 방법을 μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€.


동적 데이터 μΆ”μΆœν•˜κΈ°

동적 λ°μ΄ν„°λŠ” μ›Ή νŽ˜μ΄μ§€μ˜ λ‘λ‡Œ 역할을 ν•˜λŠ” JavaScript둜 μƒμ„±λ˜λŠ” λ°μ΄ν„°λ‘œ, μ‚¬μš©μžκ°€ μ›Ήμ‚¬μ΄νŠΈμ— μ ‘μ†ν•œ 후에 μƒμ„±λ˜κ±°λ‚˜ νŠΉμ • 행동을 μ·¨ν•˜λ©΄ 변경될 수 μžˆμŠ΅λ‹ˆλ‹€.

이와 같은 동적 λ°μ΄ν„°λŠ” BeautifulSoupκ³Ό Requestsλ‘œλŠ” κ°€μ Έμ˜¬ 수 μ—†μŠ΅λ‹ˆλ‹€.

ν•˜μ§€λ§Œ Selenium을 μ‚¬μš©ν•˜λ©΄ μ›Ή νŽ˜μ΄μ§€μ—μ„œ JavaScriptλ₯Ό μ‹€ν–‰ν•˜κ³ , 동적 데이터λ₯Ό κ°€μ Έμ˜¬ 수 μžˆμŠ΅λ‹ˆλ‹€.

μ‹€μŠ΅ ν™”λ©΄μ˜ μ½”λ“œλ₯Ό λ‹¨κ³„λ³„λ‘œ μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

μ‹€μŠ΅ μ½”λ“œλ‚΄ μ΄ν•΄ν•˜κΈ° μ–΄λ €μš΄ 뢀뢄은 ν•™μŠ΅ λ„κ΅¬μ˜ AI νŠœν„°λ₯Ό ν™œμš©ν•΄ μ§ˆλ¬Έν•΄ λ³΄μ„Έμš”.


1. ν•„μš”ν•œ νŒ¨ν‚€μ§€ 뢈러였기

  • selenium: μ›Ή νŽ˜μ΄μ§€μ—μ„œ 동적인 데이터λ₯Ό κ°€μ Έμ˜΅λ‹ˆλ‹€.

  • pandas: 데이터λ₯Ό ν‘œ ν˜•νƒœλ‘œ μ •λ¦¬ν•˜κ³  μ²˜λ¦¬ν•©λ‹ˆλ‹€.

  • webdriver: Selenium을 μ‚¬μš©ν•΄ μ›Ή λΈŒλΌμš°μ €λ₯Ό μ œμ–΄ν•©λ‹ˆλ‹€.

  • By: μ›Ή νŽ˜μ΄μ§€μ—μ„œ μš”μ†Œλ₯Ό μ°ΎλŠ” 방법을 μ§€μ •ν•©λ‹ˆλ‹€.

  • ActionChains: μ›Ή νŽ˜μ΄μ§€μ—μ„œ λ§ˆμš°μŠ€μ™€ ν‚€λ³΄λ“œ λ™μž‘μ„ μˆ˜ν–‰ν•©λ‹ˆλ‹€.

  • EC: μ›Ή νŽ˜μ΄μ§€μ—μ„œ μš”μ†Œκ°€ λ‚˜νƒ€λ‚  λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦½λ‹ˆλ‹€.


2. μ›Ή λΈŒλΌμš°μ € μ—΄κΈ°

μ›Ή λΈŒλΌμš°μ € μ—΄κΈ°
# Chrome μ›Ήλ“œλΌμ΄λ²„λ₯Ό μ‹€ν–‰ν•˜μ—¬ λΈŒλΌμš°μ € μ°½ μ—΄κΈ° driver = webdriver.Chrome() # Yahoo Finance의 'Markets' νŽ˜μ΄μ§€λ‘œ 이동 driver.get('https://finance.yahoo.com/markets/')

크둬 λΈŒλΌμš°μ €λ₯Ό μ‹€ν–‰ν•˜κ³  Yahoo Finance의 'Markets' νŽ˜μ΄μ§€λ‘œ μ΄λ™ν•©λ‹ˆλ‹€.

참고둜 Selenium은 크둬, νŒŒμ΄μ–΄ν­μŠ€ λ“± λ‹€μ–‘ν•œ λΈŒλΌμš°μ €λ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.


3. νŽ˜μ΄μ§€κ°€ μ™„μ „νžˆ λ‘œλ“œλ  λ•ŒκΉŒμ§€ λŒ€κΈ°

νŽ˜μ΄μ§€ λ‘œλ“œ λŒ€κΈ°
# νŽ˜μ΄μ§€κ°€ μ™„μ „νžˆ λ‘œλ“œλ  λ•ŒκΉŒμ§€ λŒ€κΈ° (μ΅œλŒ€ 10초 λŒ€κΈ°) wait = WebDriverWait(driver, 10)

μ›Ή νŽ˜μ΄μ§€κ°€ μ™„μ „νžˆ λ‘œλ“œλ  λ•ŒκΉŒμ§€ μ΅œλŒ€ 10초 λ™μ•ˆ κΈ°λ‹€λ¦½λ‹ˆλ‹€.

μ›Ή νŽ˜μ΄μ§€λŠ” λ‘œλ“œ μ‹œκ°„μ΄ ν•„μš”ν•  수 있기 λ•Œλ¬Έμ—, μš”μ†Œλ“€μ΄ 쀀비될 λ•ŒκΉŒμ§€ κΈ°λ‹€λ¦¬λŠ” μ‹œκ°„μ„ μ„€μ •ν•©λ‹ˆλ‹€.


4. 'Americas' μ„Ήμ…˜μ„ μ°Ύκ³ , 슀크둀 μ΄λ™ν•˜κΈ°

Americas μ„Ήμ…˜ μ°ΎκΈ°
# 'Americas'λΌλŠ” ν…μŠ€νŠΈλ₯Ό 가진 h3 νƒœκ·Έ μ°ΎκΈ° americas_section = wait.until(EC.presence_of_element_located((By.XPATH, "//h3[text()='Americas']"))) # 'Americas' μ„Ήμ…˜κΉŒμ§€ 슀크둀 이동 actions = ActionChains(driver) # 'Americas' μ„Ήμ…˜μœΌλ‘œ 마우슀 이동 actions.move_to_element(americas_section).perform()

XPATHλŠ” XML λ¬Έμ„œμ˜ νŠΉμ • 뢀뢄을 μ°ΎκΈ° μœ„ν•œ 경둜 ν‘œν˜„ λ°©λ²•μž…λ‹ˆλ‹€.

예λ₯Ό λ“€μ–΄ μœ„μ™€ 같이 'Americas'λΌλŠ” ν…μŠ€νŠΈλ₯Ό 가진 h3 μš”μ†ŒλŠ” /h3[text()='Americas']둜 ν‘œν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

XPATHλŠ” μ›Ή νŽ˜μ΄μ§€μ—μ„œ μš”μ†Œλ₯Ό 찾을 λ•Œ μ‚¬μš©ν•˜λŠ” 방법 쀑 ν•˜λ‚˜μž…λ‹ˆλ‹€.

move_to_elementλŠ” 'Americas' μ„Ήμ…˜μœΌλ‘œ 화면을 μŠ€ν¬λ‘€ν•©λ‹ˆλ‹€.


5. 'Americas' μ„Ήμ…˜μ—μ„œ ν…Œμ΄λΈ” μ°ΎκΈ°

μ§€μˆ˜ 데이터 ν…Œμ΄λΈ” μ°ΎκΈ°
# 'Americas' μ„Ήμ…˜μ˜ λΆ€λͺ¨ μš”μ†Œμ—μ„œ ν…Œμ΄λΈ” μ°ΎκΈ° parent_section = americas_section.find_element(By.XPATH, "./ancestor::section[contains(@data-testid, 'world-indices')]") # ν…Œμ΄λΈ” μ°ΎκΈ° table = parent_section.find_element(By.XPATH, ".//table")

"Americas" μ„Ήμ…˜μ΄ μ†ν•œ μƒμœ„ section νƒœκ·Έμ—μ„œ table μš”μ†Œλ₯Ό μ°ΎμŠ΅λ‹ˆλ‹€.

"./ancestor::section[contains(@data-testid, 'world-indices')]"λŠ” "Americas" μ„Ήμ…˜μ˜ λΆ€λͺ¨ μš”μ†ŒμΈ section νƒœκ·Έλ₯Ό μ°ΎλŠ” XPATHμž…λ‹ˆλ‹€.

이 ν…Œμ΄λΈ”μ—λŠ” μš°λ¦¬κ°€ ν•„μš”ν•œ 데이터(예: μ§€μˆ˜ 이름, 가격 λ“±)κ°€ ν¬ν•¨λ˜μ–΄ μžˆμŠ΅λ‹ˆλ‹€.


6. ν…Œμ΄λΈ”μ˜ 헀더와 데이터 μˆ˜μ§‘

ν…Œμ΄λΈ” 헀더 및 데이터 μˆ˜μ§‘
# ν…Œμ΄λΈ”μ˜ 헀더 μΆ”μΆœ headers = [header.text for header in table.find_elements(By.XPATH, ".//th")] # ν…Œμ΄λΈ”μ˜ ν–‰ μΆ”μΆœ rows = table.find_elements(By.XPATH, ".//tbody/tr")

table.find_elements(By.XPATH, ".//th")λŠ” ν…Œμ΄λΈ” λ‚΄μ—μ„œ th νƒœκ·Έλ₯Ό μ°Ύμ•„ 헀더λ₯Ό μΆ”μΆœν•©λ‹ˆλ‹€.

th(Table Header) νƒœκ·ΈλŠ” ν…Œμ΄λΈ”μ˜ μ—΄ 이름(예: "Name", "Price")을 λ‚˜νƒ€λ‚΄λŠ” HTML νƒœκ·Έμž…λ‹ˆλ‹€.

ν…Œμ΄λΈ”μ˜ 각 μ—΄(th)에 ν•΄λ‹Ήν•˜λŠ” 헀더(예: "Name", "Price")λ₯Ό λ¦¬μŠ€νŠΈμ— μ €μž₯ν•©λ‹ˆλ‹€.

tbody/tr을 톡해 ν…Œμ΄λΈ”μ˜ 각 ν–‰(tr, table row)에 μžˆλŠ” 데이터λ₯Ό μΆ”μΆœν•©λ‹ˆλ‹€.


7. 각 ν–‰μ—μ„œ 'Name'κ³Ό 'Price' 값을 μΆ”μΆœν•˜μ—¬ μ €μž₯

ν–‰ 데이터 μΆ”μΆœ 및 μ €μž₯
# 데이터 μ €μž₯을 μœ„ν•œ 리슀트 μ΄ˆκΈ°ν™” table_data = [] # 각 ν–‰μ˜ μ—΄ 데이터λ₯Ό μΆ”μΆœν•˜μ—¬ λ¦¬μŠ€νŠΈμ— μΆ”κ°€ for row in rows: # 각 ν–‰μ˜ μ—΄ 데이터λ₯Ό μΆ”μΆœ columns = row.find_elements(By.XPATH, ".//td") row_data = {} # λ¨Όμ € 빈 λ”•μ…”λ„ˆλ¦¬ 생성 # headers λ¦¬μŠ€νŠΈμ™€ columns 리슀트의 길이가 κ°™λ‹€κ³  κ°€μ • for i in range(len(headers)): # headers 리슀트의 i번째 μš”μ†Œλ₯Ό κ°€μ Έμ˜΄ header = headers[i] # columns 리슀트의 i번째 μš”μ†Œμ˜ ν…μŠ€νŠΈλ₯Ό κ°€μ Έμ˜΄ column_value = columns[i].text # headerλ₯Ό ν‚€λ‘œ, column_valueλ₯Ό κ°’μœΌλ‘œ ν•˜μ—¬ λ”•μ…”λ„ˆλ¦¬μ— μΆ”κ°€ row_data[header] = column_value # 데이터λ₯Ό λ¦¬μŠ€νŠΈμ— μΆ”κ°€ table_data.append(row_data)

각 행에 μžˆλŠ” 데이터λ₯Ό 반볡(forλ¬Έ)ν•˜λ©΄μ„œ, td νƒœκ·Έμ— μžˆλŠ” 데이터(μ—΄ κ°’λ“€)λ₯Ό μΆ”μΆœν•©λ‹ˆλ‹€.

이 데이터λ₯Ό row_data λ³€μˆ˜μ— λ”•μ…”λ„ˆλ¦¬ ν˜•νƒœλ‘œ μ €μž₯ν•©λ‹ˆλ‹€.

λ”•μ…”λ„ˆλ¦¬μ˜ ν‚€λŠ” header(헀더)이고, 값은 column_value(μ—΄ κ°’)μž…λ‹ˆλ‹€.

λ§ˆμ§€λ§‰μœΌλ‘œ, table_data λ¦¬μŠ€νŠΈμ— λ”•μ…”λ„ˆλ¦¬λ₯Ό μΆ”κ°€ν•©λ‹ˆλ‹€.


8. pandasλ₯Ό μ‚¬μš©ν•΄ λ°μ΄ν„°ν”„λ ˆμž„μœΌλ‘œ λ³€ν™˜

λ°μ΄ν„°ν”„λ ˆμž„μœΌλ‘œ λ³€ν™˜
# μΆ”μΆœλœ 데이터λ₯Ό νŒλ‹€μŠ€ λ°μ΄ν„°ν”„λ ˆμž„μœΌλ‘œ λ³€ν™˜ df = pd.DataFrame(table_data) # 'Name'κ³Ό 'Price' 컬럼만 μ„ νƒν•˜μ—¬ μ •λ ¬λœ λ°μ΄ν„°ν”„λ ˆμž„ 좜λ ₯ df_filtered = df[['Name', 'Price']] # μ •λ ¬λœ 데이터 좜λ ₯ print(df_filtered)

μΆ”μΆœν•œ 데이터λ₯Ό pandas.DataFrame으둜 λ³€ν™˜ν•©λ‹ˆλ‹€.

데이터 ν”„λ ˆμž„μ—λŠ” ν…Œμ΄λΈ”μ˜ 데이터가 μ•„λž˜μ™€ 같이 μ €μž₯λ©λ‹ˆλ‹€.

NamePrice
......
......

9. 'Name'κ³Ό 'Price' 컬럼만 μ„ νƒν•˜κ³  μ •λ ¬

Nameκ³Ό Price 컬럼 선택 및 μ •λ ¬
df_filtered = df[['Name', 'Price']]

λ°μ΄ν„°ν”„λ ˆμž„μ—μ„œ 'Name'κ³Ό 'Price' 컬럼만 μ„ νƒν•˜κ³ , 'Name' μ»¬λŸΌμ„ κΈ°μ€€μœΌλ‘œ μ •λ ¬ν•©λ‹ˆλ‹€.

Guidelines

AI Tutor

Publish

Design

Upload

Notes

Favorites

Help

Code Editor

Run
Generate

Execution Result