goodthings4me.tistory.com
■ 파이썬(Python) BeautifulSoup의 객체 관련 함수인 find(), find_all()를 활용한 네이버 금융의 국내증시 주가(시고저종) 부분 크롤링
- url, headers, params를 인자로 전달하면 BeautifulSoup 객체를 return하는 function 만들어서 사용
- 종목코드를 입력하면 오늘, 전일, 고가(상한가), 거래량, 시가, 저가(하한가), 거래대금 추출할 수 있음
- 네이버 금융>국내증시의 페이지 소스 보기와 개발자도구(F12)에서 소스 코드 내용이 상이한 부분이 있음(<em> 태그와 <span> 태그 중 보이지 않거나 속성이 변경되는 경우가 있음)
▷ 페이지 소스
<div id="chart_area" class="spot">
<div class="rate_info">
<dl class="blind">
<dt><strong>삼성전자</strong></dt>
<dd>오늘의시세 58,100 포인트</dd>
<dd>900 포인트 하락</dd>
<dd>1.53% 마이너스</dd>
</dl>
<div class="today">
<p class="no_today">
<em class="no_down">
<span class="blind">58,100</span>
<span class="no5">5</span><span class="no8">8</span><span class="shim">,</span><span
class="no1">1</span><span class="no0">0</span><span class="no0">0</span>
</em>
</p>
<p class="no_exday">
<span class="sptxt sp_txt1">전일대비</span>
<em class="no_down">
<span class="ico down">하락</span>
<span class="blind">900</span>
<span class="no9">9</span><span class="no0">0</span><span class="no0">0</span>
</em>
<span class="bar">l</span>
<em class="no_down">
<span class="ico minus">-</span>
<span class="blind">1.53</span>
<span class="no1">1</span><span class="jum">.</span><span class="no5">5</span><span
class="no3">3</span>
<span class="per">%</span>
</em>
</p>
</div>
<table summary="주요 시세(전일종가, 시고저가, 거래량, 거래대금)을 제공합니다." class="no_info">
<caption>주요 시세</caption>
<colgroup>
<col>
<col width="214">
<col width="157">
</colgroup>
<tr>
<td class="first">
<span class="sptxt sp_txt2">전일</span>
<em>
<span class="blind">59,000</span>
<span class="no5">5</span><span class="no9">9</span><span class="shim">,</span><span
class="no0">0</span><span class="no0">0</span><span class="no0">0</span>
</em>
</td>
<td>
<span class="sptxt sp_txt4">고가</span>
<em class="no_down">
<span class="blind">58,500</span><span class="no5">5</span><span class="no8">8</span><span
class="shim">,</span><span class="no5">5</span><span class="no0">0</span><span
class="no0">0</span>
</em>
<span class="sptxt sp_txt6">(상한가</span>
<em class="no_cha">
<span class="blind">76,700</span><span class="no7">7</span><span class="no6">6</span><span
class="shim">,</span><span class="no7">7</span><span class="no0">0</span><span
class="no0">0</span>
</em>
<span class="sptxt sp_txt8">)</span>
</td>
<td>
<span class="sptxt sp_txt9">거래량</span>
<em>
<span class="blind">7,385,852</span>
<span class="no7">7</span><span class="shim">,</span><span class="no3">3</span><span
class="no8">8</span><span class="no5">5</span><span class="shim">,</span><span
class="no8">8</span><span class="no5">5</span><span class="no2">2</span>
</em>
</td>
</tr>
<tr>
<td class="first">
<span class="sptxt sp_txt3">시가</span>
<em class="no_down">
<span class="blind">58,200</span><span class="no5">5</span><span class="no8">8</span><span
class="shim">,</span><span class="no2">2</span><span class="no0">0</span><span
class="no0">0</span>
</em>
</td>
<td>
<span class="sptxt sp_txt5">저가</span>
<em class="no_down">
<span class="blind">58,000</span><span class="no5">5</span><span class="no8">8</span><span
class="shim">,</span><span class="no0">0</span><span class="no0">0</span><span
class="no0">0</span>
</em>
<span class="sptxt sp_txt7">(하한가</span>
<em class="no_cha">
<span class="no4">4</span><span class="no1">1</span><span class="shim">,</span><span
class="no3">3</span><span class="no0">0</span><span class="no0">0</span>
</em>
<span class="sptxt sp_txt8">)</span>
</td>
<td>
<span class="sptxt sp_txt10">거래대금</span>
<em>
<span class="blind">430,148</span>
<span class="no4">4</span><span class="no3">3</span><span class="no0">0</span><span
class="shim">,</span><span class="no1">1</span><span class="no4">4</span><span
class="no8">8</span>
</em>
<span class="sptxt sp_txt11">백만</span>
</td>
</tr>
</table>
</div>
▷ 크롤링 연습 코드
import requests
from bs4 import BeautifulSoup
## BeautifulSoup 객체 반환 함수
def get_bs_obj(url, headers = None, params = None):
result = requests.get(url, headers = headers, params = params)
soup = BeautifulSoup(result.content, 'html.parser')
return soup
## company_code를 받아서 price를 리턴하는 함수
def get_price(company_code):
url = 'https://finance.naver.com/item/main.nhn' #?code=005930'
params = {
'code': company_code,
}
## BeautifulSoup 객체 생성 (모듈 이용)
soup = get_bs_obj(url, params = params)
## 찾는 종목코드가 없으면 None 리턴
## AttributeError: 'NoneType' object has no attribute 'find'
try:
company_name = soup.find('div', {'class':'h_company'}).find('h2')
company_name = company_name.text ## 회사명
except:
return None
no_today = soup.find('p', {'class':'no_today'})
#print(no_today)
## span 태그 사라지는 현상 대비하여 if문으로 분기
bl = no_today.find('span', {'class':'blind'})
if bl:
price = bl.text.strip() ## 주가 금액 부분
else:
price = no_today.em.text.strip()
#print(price)
# 전일, 고가, 시가, 저가 추출 위해서
# fina_all()은 단계적으로 접근함 (table만 추출 후, tr 2개 추출)
table = soup.find('table', {'class':'no_info'})
#print(table)
trs = table.find_all('tr') ##
#print(trs)
## 그러나, 종목코드별 주가 존재 여부에 따라 em, span 태그 수정되어서 일부 데이터 누락됨
# close = trs[0].find_all('td')[0].find_all('span')[1].text ## 전일
# high = trs[0].find_all('td')[1].find_all('span')[1].text ## 고가
# if trs[0].find_all('td')[1].find('span', {'class':'blind'}):
# upper = trs[0].find_all('td')[1].find_all('span')[9].text ## 상한가
# else:
# upper = trs[0].find_all('td')[1].find_all('span')[10].text
# trade_vol = trs[0].find_all('td')[2].find_all('span')[1].text ## 거래량
# current = trs[1].find_all('td')[0].find_all('span')[1].text ## 시가
# low = trs[1].find_all('td')[1].find_all('span')[1].text ## 저가
# lower = trs[1].find_all('td')[1].find('em', class_ = 'no_cha').get_text(strip=True, separator='') ## 하한가
# trade_val = trs[1].find_all('td')[2].find_all('span')[1].text ## 거래대금
## 전일, 고가(상한가), 거래량
bl01 = trs[0].find_all('td')[0].find('span', {'class':'blind'})
if bl01:
close = bl01.text.strip()
else:
close = trs[0].find_all('td')[0].em.text.strip()
bl02 = trs[0].find_all('td')[1].find_all('em')[0].find('span', {'class':'blind'})
if bl02:
high = bl02.text.strip()
else:
high = trs[0].find_all('td')[1].find_all('em')[0].text.strip()
bl03 = trs[0].find_all('td')[1].find_all('em')[1].find('span', {'class':'blind'})
if bl03:
upper = bl03.text.strip()
else:
upper = trs[0].find_all('td')[1].find_all('em')[1].text.strip()
bl04 = trs[0].find_all('td')[2].find('span', {'class':'blind'})
if bl04:
trade_vol = bl04.text.strip()
else:
trade_vol = trs[0].find_all('td')[2].em.text.strip()
## 시가, 저가(하한가), 거래대금
bl05 = trs[1].find_all('td')[0].find('span', {'class':'blind'})
if bl05:
current = bl05.text.strip()
else:
current = trs[1].find_all('td')[0].em.text.strip()
bl06 = trs[1].find_all('td')[1].find_all('em')[0].find('span', {'class':'blind'})
if bl06:
low = bl06.text.strip()
else:
low = trs[1].find_all('td')[1].find_all('em')[0].text.strip()
bl07 = trs[1].find_all('td')[1].find_all('em')[1].find('span', {'class':'blind'})
if bl07:
lower = bl07.text.strip()
else:
lower = trs[1].find_all('td')[1].find_all('em')[1].text.strip()
bl08 = trs[1].find_all('td')[2].find('span', {'class':'blind'})
if bl08:
trade_val = bl08.text.strip()
else:
trade_val = trs[1].find_all('td')[2].em.text.strip()
return {'company_name':company_name, 'price':price, 'close':close, 'high':high,\
'upper':upper, 'trade_vol':trade_vol, 'current':current, 'low':low,\
'lower':lower, 'trade_val':trade_val}
codes = ['005930', '051900', '051905', '003240', '000009', '051910']
## codes 리스트의 종목코드를 찾아 결과를 리턴한 내역을 for문으로 출력함
for code in codes:
result = get_price(code) ## 함수 호출
## 종목코드가 없을 경우 None 리턴
if result == None:
print('종목코도 {} : {}\n{}'.format(code, None, '=' * 50))
continue
print('\n회사명: {0}\n오늘: {1}\n전일: {2}\n고가: {3} (상한가 {4})\n거래량: {5}주\n시\
가: {6}\n저가: {7} (하한가 {8})\n거래대금: {9}백만\n'.\
format(result['company_name'], result['price'], result['close'], result['high'], \
result['upper'], result['trade_vol'], result['current'], result['low'], \
result['lower'], result['trade_val']))
print('=' * 50)
[실행 결과]
회사명: 삼성전자
오늘: 58,100
전일: 59,000
고가: 58,500 (상한가 76,700)
거래량: 20,259,626주
시가: 58,200
저가: 57,500 (하한가 41,300)
거래대금: 1,175,233백만
==================================================
회사명: LG생활건강
오늘: 1,509,000
전일: 1,524,000
고가: 1,522,000 (상한가 1,981,000)
거래량: 19,907주
시가: 1,521,000
저가: 1,496,000 (하한가 1,067,000)
거래대금: 29,972백만
==================================================
회사명: LG생활건강우
오늘: 699,000
전일: 706,000
고가: 704,000 (상한가 917,000)
거래량: 4,711주
시가: 704,000
저가: 695,000 (하한가 495,000)
거래대금: 3,294백만
==================================================
회사명: 태광산업
오늘: 696,000
전일: 707,000
고가: 702,000 (상한가 919,000)
거래량: 672주
시가: 701,000
저가: 693,000 (하한가 495,000)
거래대금: 467백만
==================================================
종목코도 000009 : None
==================================================
회사명: LG화학
오늘: 650,000
전일: 642,000
고가: 653,000 (상한가 834,000)
거래량: 314,790주
시가: 629,000
저가: 629,000 (하한가 450,000)
거래대금: 202,062백만
==================================================
[참고] 한입에 크롤링 - Kyeongrok Kim
'코딩 연습 > 코딩배우기' 카테고리의 다른 글
파이썬 크롤링(Crawling) 연습 - BeautifulSoup 활용 기초 (0) | 2020.11.03 |
---|---|
파이썬 크롤링(Crawling) 연습 - Daum에서 검색한 전화번호의 기본 정보 추출 (0) | 2020.11.01 |
파이썬 크롤링(Crawling) 연습 - BeautifulSoup 객체를 모듈로 만들어서 사용해보기 (0) | 2020.10.27 |
파이썬 웹 크롤링(Web Crawling) 알아보기 #9 (0) | 2020.10.26 |
파이썬 웹 크롤링(Web Crawling) 알아보기 #8 (0) | 2020.10.26 |
댓글