Skip to content

๐Ÿš€ ์ฃผ์‹ ์ •๋ณด ์ˆ˜์ง‘ ํ”„๋กœ๊ทธ๋žจ(Toy-Project)

Notifications You must be signed in to change notification settings

kim-src/StockScraper

Folders and files

NameName
Last commit message
Last commit date

Latest commit

ย 

History

25 Commits
ย 
ย 
ย 
ย 

Repository files navigation

๐ŸŽ Tunnel


โœ… StockScraper ์†Œ๊ฐœ

  • ๊ฐœ๋ฐœ ํ™˜๊ฒฝ : Google Colab
  • ๊ฐœ๋ฐœ ๋ชฉ์  : Python์„ ์ด์šฉํ•œ ์›น ํฌ๋กค๋ง ๊ฒฝํ—˜ ๋ฐ Colab ํ™œ์šฉ ๊ฒธํ—˜ ์Šต๋“
  • ๊ฐœ๋ฐœ ๋‚ด์šฉ : ๋„ค์ด๋ฒ„ ์ฆ๊ถŒ ์‚ฌ์ดํŠธ๋ฅผ ์ด์šฉํ•œ ์‚ผ์„ฑ์ „์ž ์ฃผ์‹ ์ •๋ณด ์ˆ˜์ง‘
  • ๊ฐœ๋ฐœ ์—ญ๋Ÿ‰ : Colab ํ™œ์šฉ, Python์˜ BeautifulSoup, Pandas, Requests ํ™œ์šฉ, ์›น ํฌ๋กค๋ง ์ดํ•ด
  • ์ƒ์„ธ ๋‚ด์šฉ : ์›น ํฌ๋กค๋ง์„ ์ด์šฉํ•œ ๋ฐ์ดํ„ฐ ๋ถ„์„ (๋ธ”๋กœ๊ทธ ์นดํ…Œ๊ณ ๋ฆฌ)
  • ๊ฐœ๋ฐœ์— ํ•„์š”ํ–ˆ๋˜ ๊ธฐ๋Šฅ :
    Google Colab Python BeautifulSoup Pandas Requests

๐ŸŽฏ ํ•™์Šต ๊ฒฐ๋ก 

  • ์›น ํฌ๋กค๋ง ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ„๋‹จํ•œ ํ”„๋กœ๊ทธ๋žจ์„ ์ œ์ž‘ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์›น ํฌ๋กค๋ง์„ ์ด์šฉํ•˜์—ฌ HTML๋กœ ๊ตฌ์„ฑ๋œ ์›น ํŽ˜์ด์ง€ ์ •๋ณด๋ฅผ ์‰ฝ๊ฒŒ ๊ฐ€์ ธ์˜ฌ ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋” ๋‚˜์•„๊ฐ€๋ฉด ๊ฒ€์ƒ‰ ์—”์ง„ ํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ์— ํ™œ์šฉ๋  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋Ÿฐ๋ฐ ์›น ํฌ๋กค๋ง์€ ์ˆ˜๋งŽ์€ ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐฉ๋ฒ• ์ค‘ ๋‹จ์ง€ ํ•˜๋‚˜์˜ ๋„๊ตฌ์ผ๋ฟ์ด์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋ฌผ๋ก  ์ž๋™ํ™” ํ”„๋กœ๊ทธ๋žจ ๊ฐœ๋ฐœ๋„ ์ค‘์š”ํ•˜์ง€๋งŒ ๋ฐ์ดํ„ฐ ์ˆ˜์ง‘ ๊ณ„ํš ๋ฐ ํ•ด์„ ๋ฐฉ๋ฒ•์ด ๋” ์ค‘์š”ํ•œ ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹ค.

๐Ÿ”” ๋ฐฐ๊ฒฝ ์ง€์‹

๐Ÿ“Œ ์›น ํฌ๋กค๋ง(Web Crawling)

  • ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋˜๋Š” ๊ฒ€์ƒ‰ ์—”์ง„ ๊ตฌ์ถ•์˜ ํ•œ ๋ฐฉ๋ฒ•์œผ๋กœ ์›น ํŽ˜์ด์ง€์— ์žˆ๋Š” ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.
  • Pyhton์˜ ๋ฐ˜๋ณต๋ฌธ ๋ฐ Requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์ด์šฉํ•˜๋ฉด ์›น ํฌ๋กค๋ง ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋ธ”๋กœ๊ทธ ๊ธ€์—์„œ๋Š” ์›น ํฌ๋กค๋ง ๊ธฐ๋Šฅ์„ ์ด์šฉํ•œ ์ฃผ์‹ ์ •๋ณด ๋ฐ์ดํ„ฐ ๋ถ„์„ ๋ฐฉ๋ฒ•์„ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๐Ÿ“Œ BeautifulSoup

  • BeautifulSoup๋Š” ๋Œ€ํ‘œ์ ์ธ ์›น ํฌ๋กค๋ง ๋ชฉ์ ์˜ Python ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  • BeautifulSoup๋Š” HTML ๋˜๋Š” XML ๋“ฑ์˜ ์–ธ์–ด์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ถ”์ถœํ•˜๋Š” ๊ธฐ๋Šฅ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ“Œ Pandas

  • Pandas๋Š” ๋ฐ์ดํ„ฐ ๊ฐ€๊ณต ๋ชฉ์ ์˜ Python ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ž…๋‹ˆ๋‹ค.
  • ๋ฐ์ดํ„ฐ ๋ถ„์„ ์‹œ ๋ฐ์ดํ„ฐ๋ฅผ DB ํ˜•์‹์œผ๋กœ ๋น ๋ฅด๊ฒŒ ๋ณ€ํ™˜์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๋˜๋Š” ๋‹ค์–‘ํ•œ ๋ฐ์ดํ„ฐ์™€ ์กฐํ•ฉ์‹œํ‚ค๊ฑฐ๋‚˜ ๋ฐ์ดํ„ฐ ํ•„ํ„ฐ๋ง ์‹œ ์ด์šฉ๋ฉ๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ BeautifulSoup๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ์ทจ๋“ํ•œ ํ›„ Pandas๋กœ ๋ณ€ํ™˜ํ•˜๋Š” ์ž‘์—…์„ ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.





from bs4 import BeautifulSoup # BeautifulSoup ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
import requests # Requests ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

for page in range(1, 6): # ํŽ˜์ด์ง€ ์ˆ˜๋ฅผ ์˜๋ฏธํ•˜๋Š” 1๋ถ€ํ„ฐ 5๊นŒ์ง€์˜ ์ˆซ์ž์— ๋Œ€ํ•ด ๋ฐ˜๋ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  print(str(page))
  # ํ˜„์žฌ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ๋ฅผ ์ถœ๋ ฅํ•˜๋„๋ก ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  
  url_005930 = "http://finance.naver.com/item/sise_day.nhn?code=005930" + "&page=" + str(page)
  # ๋„ค์ด๋ฒ„ ๊ธˆ์œต์˜ ์‚ผ์„ฑ์ „์ž์˜ ์ฃผ์‹ ์ •๋ณด๊ฐ€ ์žˆ๋Š” ํŽ˜์ด์ง€์—์„œ ํŽ˜์ด์ง€ ๋ฒˆํ˜ธ(&page=)๋ฅผ str(page) ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ถ”๊ฐ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  headers = {"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"}
  # ์›น ์„œ๋ฒ„๊ฐ€ ์›น ํฌ๋กค๋ง ์š”์ฒญ์„ ์›น ๋ธŒ๋ผ์šฐ์ €์—์„œ ์˜จ ๊ฒƒ์œผ๋กœ ์ธ์‹ํ•˜๊ฒŒ ํ•˜๊ธฐ ์œ„ํ•ด User-Agent ํ—ค๋” ์ •๋ณด๋ฅผ ์ž‘์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  # ์ฐธ๊ณ ๋กœ User-Agent ์ •๋ณด๋Š” 'https://useragentstring.com/'์—์„œ ํš๋“ํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ ์ด๋Š” ์‚ฌ์šฉ์ž์˜ ์›น ํ™˜๊ฒฝ ๋“ฑ์˜ ์ •๋ณด์ž…๋‹ˆ๋‹ค.

  response = requests.get(url_005930, headers=headers)
  # ์„ค์ •ํ•œ url์— HTTP GET ์š”์ฒญ์„ ๋ณด๋‚ธ ํ›„ response ๋ณ€์ˆ˜์— ํ•ด๋‹น ์‘๋‹ต์„ ์ €์žฅํ•˜๊ฒŒ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

  soup = BeautifulSoup(response.text, "html.parser")
  # response์— ์ €์žฅ๋œ ์‘๋‹ต ์ค‘ HTML ๋‚ด์šฉ์„ ์‚ฌ์šฉํ•˜์—ฌ BeautifulSoup ๊ฐ์ฒด๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  # BeautifulSoup ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•˜์—ฌ HTML ๋‚ด์šฉ์„ ํŒŒ์‹ฑ(๋ถ„์„)ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  parsing_list = soup.find_all("tr")
  # HTML ๋‚ด์šฉ ์ค‘ 'tr' ํƒœ๊ทธ๊ฐ€ ํฌํ•จ๋œ ๋ชจ๋“  ๋ฌธ์ž์—ด(ํ–‰)์„ ์ฐพ์•„ ๋ฆฌ์ŠคํŠธ๋กœ ๋ฐ˜ํ™˜์‹œ์ผฐ์Šต๋‹ˆ๋‹ค.

  isCheckNone = None
  # None ๊ฐ’์— ๋Œ€ํ•œ ๋น„๊ต๋ฅผ ์œ„ํ•œ ๋ณ€์ˆ˜๋ฅผ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  
  for i in range(1, len(parsing_list)):
  # parsing_list ๋‚ด์šฉ์— ์žˆ๋Š” 'tr' ํƒœ๊ทธ๊ฐ€ ํฌํ•จ๋œ ํ–‰์„ ๋ฐ˜๋ณตํ•˜์˜€์Šต๋‹ˆ๋‹ค.

    if(parsing_list[i].span != isCheckNone):
    # ์œ ํšจํ•œ ๋ฐ์ดํ„ฐ ํ–‰ ์ •๋ณด๋งŒ ์ทจ๋“ํ•˜๊ธฐ ์œ„ํ•ด 'span' ํƒœ๊ทธ์˜ ๋‚ด์šฉ์ด None์ด ์•„๋‹Œ์ง€ ํ™•์ธํ•˜์˜€์Šต๋‹ˆ๋‹ค.

      print(parsing_list[i].find_all("td", align="center")[0].text,
            # ํ•ด๋‹น 'tr' ํƒœ๊ทธ ๋‚ด์—์„œ 'td' ํƒœ๊ทธ ์ค‘ align ์†์„ฑ์ด "center"์ธ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ([0])์˜ ํ…์ŠคํŠธ(๋‚ ์งœ)๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.

            parsing_list[i].find_all("td", class_="num")[0].text)
            # ๊ฐ™์€ 'tr' ํƒœ๊ทธ ๋‚ด์—์„œ 'td' ํƒœ๊ทธ ์ค‘ class ์†์„ฑ์ด "num"์ธ ์ฒซ ๋ฒˆ์งธ ์š”์†Œ([0])์˜ ํ…์ŠคํŠธ(์ฃผ์‹ ์ข…๊ฐ€)๋ฅผ ์ถœ๋ ฅํ•ฉ๋‹ˆ๋‹ค.