프로젝트 - 웹데이터 분석 (네이버 금융)

허재정·2024년 2월 23일

EDA

목록 보기
6/13
post-thumbnail

네이버 금융

1. 웹페이지 개발자 도구

  • 인터넷에 html을 보기 위한 도구
  • 크롬 오른쪽 상단 ... > 도구 더보기 > 개발자 도구 또는 그냥 F12

2. 원하는 html 태그 위치 찾아가기

  • html태그 위치 : 부분
soup.find_all("span", "value")[0].string
  # 실행결과
  '1,146.00'

3. url접근 (urllib의 request 모듈 필요)

# 네이버 금융
  from urllib.request import urlopen
  from bs4 import BeautifulSoup
  
  url = "https://finance.naver.com/"
  response = urlopen(url)
  response.status
  >> 200 - 웹페이지 정상 상태
  • 4개 li 리스트 (미국/일본/유럽연합/중국)

  • 그 내부의 a태그 가져오기

  • 그 내부의 값 하나씩 뽑아내기


3. html데이터 가져오기

# import
from urllib.request import urlopen #(웹페이지 이용이란 요청하고 응답하는 것임)
from bs4 import BeautifulSoup

url = "https://finance.naver.com/marketindex/"
# page = urlopen(url)
# response , res  라고도 사용 (웹페이지 이용이란 요청하고 응답하는 것임)
response = urlopen(url)
# response.status (google에서 HTTP 상태 코드 검색하면 숫자에 따른 상태의미 알수있음)
soup = BeautifulSoup(response, "html.parser")
print(soup.prettify())

결과

<head>
  <title>
   네이버 증권
  </title>
  <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
  <meta content="text/javascript" http-equiv="Content-Script-Type"/>
  <meta content="text/css" http-equiv="Content-Style-Type"/>
  <meta content="네이버 증권" name="apple-mobile-web-app-title"/>
  <meta content="네이버 증권" property="og:title"/>
  <meta content="https://ssl.pstatic.net/static/m/stock/im/2016/08/og_stock-200.png" property="og:image"/>
  <meta content="https://finance.naver.com" property="og:url"/>
  <meta content="국내 해외 증시 지수, 시장지표, 뉴스, 증권사 리서치 등 제공" property="og:description"/>
  <meta content="article" property="og:type"/>
  <meta content="" property="og:article:thumbnailUrl"/>
  <meta content="네이버 증권" property="og:article:author"/>
  <meta content="http://FINANCE.NAVER.COM" property="og:article:author:url"/>
  <link href="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/css/finance_header.css" rel="stylesheet" type="text/css"/>
  <link href="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/css/finance.css" rel="stylesheet" type="text/css"/>
  <link href="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/css/newstock3.css" rel="stylesheet" type="text/css"/>
  <script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/jindo.min.ns.1.5.3.euckr.js" type="text/javascript">
  </script>
  <script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/release/common.js" type="text/javascript">
  </script>
  <script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/jindoComponent/jindo.Component.1.0.3.js" type="text/javascript">

4. 데이터 추출하기 (태그 가져오기)

(방법1)

soup.find_all("span","value"), len(soup.find_all("span","value"))
    
# 실행결과
([<span class="value">1,336.00</span>,
  <span class="value">887.68</span>,
  <span class="value">1,435.40</span>,
  <span class="value">185.03</span>,
  <span class="value">149.8800</span>,
  <span class="value">1.0775</span>,
  <span class="value">1.2584</span>,
  <span class="value">104.2000</span>,
  <span class="value">77.59</span>,
  <span class="value">1618.4</span>,
  <span class="value">2014.9</span>,
  <span class="value">85846.55</span>],
 12)

(방법2)

soup.find_all("span", class_="value"), len(soup.find_all("span","value"))
# 실행결과
>>
([<span class="value">1,336.00</span>,
  <span class="value">887.68</span>,
  <span class="value">1,435.40</span>,
  <span class="value">185.03</span>,
  <span class="value">149.8800</span>,
  <span class="value">1.0775</span>,
  <span class="value">1.2584</span>,
  <span class="value">104.2000</span>,
  <span class="value">77.59</span>,
  <span class="value">1618.4</span>,
  <span class="value">2014.9</span>,
  <span class="value">85846.55</span>],
 12)

(방법3) : 갯수 확인까지 (+ len( ))

soup.find_all("span", {"class":"value"}), len(soup.find_all("span","value"))
    
#실행결과
>>
([<span class="value">1,336.00</span>,
  <span class="value">887.68</span>,
  <span class="value">1,435.40</span>,
  <span class="value">185.03</span>,
  <span class="value">149.8800</span>,
  <span class="value">1.0775</span>,
  <span class="value">1.2584</span>,
  <span class="value">104.2000</span>,
  <span class="value">77.59</span>,
  <span class="value">1618.4</span>,
  <span class="value">2014.9</span>,
  <span class="value">85846.55</span>],
 12)

5. 태그에서 텍스트만 추출하기

* (방법 1)
soup.find_all("span",{"lacss": "value"})[0] 

* (방법 2)
soup.find_all("span",{"class":"value"})[0].text

* (방법 3)
soup.find_all("span",{"class":"value"})[0].string
   
* (방법 4)
soup.find_all("span",{"class":"value"})[0].get_text()

>> '1,336.00'

6. urllib 모듈 - request로 url에 접근 (네이버금융 : 예제1-2)

  • !pip install requests
  • find, find_all
  • select, select_one
  • find, select_one : 단일선택
  • select, find_all : 다중선택
  • requests 임포트
import requests
# from urllib.request.Request
from bs4 import BeautifulSoup

url = "https://finance.naver.com/marketindex/"
response = requests.get(url)
#requests.get(), requests.post() #equest에는 get방식과 post방식이 있다.
soup = BeautifulSoup(response.text, "html.parser")
print(soup.prettify())
# requests.get()
# requests.post() 

reponse
# 실행결과
>> <Response [200]> 
    
# 실행결과
>> 
Output exceeds the size limit. Open the full output data in a text editor<script language="javascript" src="/template/head_js.naver?referer=info.finance.naver.com&amp;menu=marketindex&amp;submenu=market">
</script>
<script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/info/jindo.min.ns.1.5.3.euckr.js" type="text/javascript">
</script>
<script src="https://ssl.pstatic.net/imgstock/static.pc/20230321170048/js/jindo.1.5.3.element-text-patch.js" type="text/javascript">
</script>
<div id="container" style="padding-bottom:0px;">
 <div class="market_include">
  <div class="market_data">
   <div class="market1">
    <div class="title">
     <h2 class="h_market1">
      <span>
       환전 고시 환율
      </span>
     </h2>
    </div>
    <!-- data -->
    <div class="data">
     <ul class="data_lst" id="exchangeList">
      <li class="on">
       <a class="head usd" href="/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW" onclick="clickcr(this, 'fr1.usdt', '', '', event);">
        <h3 class="h_lst">
         <span class="blind">
          미국 USD

7. 태그 리스트 가져오기

  • li 태그의 on 클래스
  • 그 안에 있는 a태그 가져오기
  • 그 안에 있는 값들을 하나씩 뽑아냄
soup.find_all("li","on") # li 태그의 on 클래스

# 실행결과
>>
Output exceeds the size limit. Open the full output data in a text editor[<li class="on">
 <a class="head usd" href="/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW" onclick="clickcr(this, 'fr1.usdt', '', '', event);">
 <h3 class="h_lst"><span class="blind">미국 USD</span></h3>
 <div class="head_info point_dn">
 <span class="value">1,319.00</span>
 <span class="txt_krw"><span class="blind"></span></span>
 <span class="change"> 0.50</span>
 <span class="blind">하락</span>
 </div>
 </a>
 <a class="graph_img" href="/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW" onclick="clickcr(this, 'fr1.usdc', '', '', event);">
 <img alt="" height="153" src="https://ssl.pstatic.net/imgfinance/chart/marketindex/FX_USDKRW.png" width="295"/>
 </a>
 <div class="graph_info">
 <span class="time">2023.04.07 22:00</span>
 <span class="source">하나은행 기준</span>
 <span class="count">고시회차<span class="num">321</span></span>
 </div>
 </li>,
 <li class="on">
 <a class="head jpy_usd" href="/marketindex/worldExchangeDetail.naver?marketindexCd=FX_USDJPY" onclick="clickcr(this, 'fr2.jpyut', '', '', event);">
 <h3 class="h_lst"><span class="blind">달러/일본 엔</span></h3>
 <div class="head_info point_up">
 <span class="value">132.1100</span>
 <span class="txt_jpy"><span class="blind"></span></span>
...

8. 4개 데이터 수집 (li태그)

exchange_datas = []
baseurl = "https://finance.naver.com"

for item in exchangeList:
    data = {
        "title": item.select_one(".h_lst").text,
        "exchange" : item.select_one(".value").text,
        "change" : item.select_one(".change").text,
        "updown" : item.select_one("div.head_info.point_dn> .blind"),
        "link" : baseurl + item.select_one("a").get("href")
    }
    print(data)
    exchange_datas.append(data)
exchange_datas
# 실행결과


9. 태그 리스트 가져오기

  • a 태그 가져오기
baseurl = "https://finance.naver.com"
baseurl +exchangeList[0].select_one("a").get("href") 

# 실행결과
'https://finance.naver.com/marketindex/exchangeDetail.naver?marketindexCd=FX_USDKRW'
   
# 엑셀파일로 저장
df = pd.DataFrame(exchange_datas)
df.to_excel("./naverfinance.xlsx")

10. select로 텍스트 리스트 가져오기

- select 사용법 : 클래스는 앞에 점(.) id는 앞에 샾(#)
- blind 부분은 2곳에 쓰였으므로 구분해주기 위함
- head_info point_dn 는 속성값 - 2개 (head_info 와 point_dn) - 띄어쓰기 주의
- 띄어쓰기는 점(.)으로 대체 가능
- div.head_info.point_dn > .blind 에서 > 는 바로 밑의 하위를 뜻함 (여기서는 '하락')
- > 가 없다면 첫번째로 나오는 '원' 을 가져옴
title = exchangeList[0].select_one(".h_lst").text  # '미국 USD'
exchange = exchangeList[0].select_one(".value").text # '1,319.00'
change = exchangeList[0].select_one(".change").text
updown = exchangeList[0].select_one("div.head_info.point_dn > .blind").text
 
title, exchange, change, updown
# 실행결과
>>
('미국 USD', '1,319.00', ' 0.50', '하락')

BeautifulSoup 예제 2 - 위키백과 문서 정보 가져오기

# google에서 여명의 눈동자 찾으면 위키백과.. 거기 url의 한글 부분이 숫자와 문자로 섞여서 표현됨.  
# 깨져있는 제목 부분을 google서 decode 치고 그 중 하나 골라서 오픈 후 위의 url 입력 후 decode한 것을 붙이면 됨.  
# 여기서는 그 깨진 한글 부분을 {search_words}라 표현
   
import urllib
from urllib.request import urlopen, Request
html = "https://ko.wikipedia.org/wiki/{search_words}"
   
# 여명의_눈동자
# https://ko.wikipedia.org/wiki/여명의_눈동자
req = Request(html.format(search_words=urllib.parse.quote("여명의_눈동자"))) #글자를 url로 encoding
   
response = urlopen(req)
soup = BeautifulSoup(response, "html.parser")
print(soup.prettify)

n = 0

for each in soup.find_all("ul"):
 print("=>" + str(n) + "===========================")
 print(each.get_text())
 n += 1

soup.find_all("ul")[35].text.strip().replace("\xa0","")


Python List 데이터형 (대괄호로 생성)

colors = ["red","blue","green"]
colors[0], colors[1], colors[2]
# 실행결과

('red', 'blue', 'green')

b = colors
b
# 실행결과

['red', 'black', 'green']

c = colors.copy()
c
# 실행결과

['red', 'black', 'green']

c[1] ="yellow"
c
# 실행결과
['red', 'yellow', 'green']
---------------------------------------------------------------------
- List형을 반복문(for)적용

for color in colors:
 print(color)

  • in 명령으로 조건문(if)에 적용
if "white" in colors:
    print("True")

movies = ["라라랜드","먼 훗날 우리","어벤저스","다크나이트","타이타닉"]
print(movies)
  • append : list 제일 뒤에 추가
  • pop : list 제일 뒤부터 자료를 하나씩 삭제
movies.pop()
# 실행결과

  • extend : 제일 뒤에 자료 추가
  • remove : 자료를 삭제
  • slicing : [n:m] n번째 부터 n-1
  • insert : 원하는 위치에 자료 삽입
  • list 안에 list
favorite_movies.insert(5, ["레오나르도 디카프리오"])
favorite_movies

  • isinstance(favorite_movies, list)
for each_item in favorite_movies:
    if isinstance(each_item, list):
        for nested_item in each_item:
            print("nested_item", nested_item)
    else:
        print("each_item", each_item)   

profile
Data Science 스터디로그

0개의 댓글