오늘은 파이썬을 이용하여 네이버 증권에서 시가총액순으로 나와있는 종목 정보를 크롤링하려고 한다.
다음 페이지 주소는 다음과 같다.
https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page=1
보면 sosok이 0인경우 코스피 sosok이 1인경우 코스닥인 것을 확인할 수 있다.
이제 크롬 개발자 도구로 소스를 Request된 data를 살펴보면
<tr onMouseOver="mouseOver(this)" onMouseOut="mouseOut(this)">
<td class="no">1</td>
<td><a href="/item/main.naver?code=005930" class="tltle">삼성전자</a></td>
<td class="number">58,300</td>
<td class="number">
<em class="bu_p bu_pup"><span class="blind">상승</span></em><span class="tah p11 red02">
2,400
</span>
</td>
<td class="number">
<span class="tah p11 red01">
+4.29%
</span>
</td>
<td class="number">100</td>
<td class="number">3,480,383</td>
<td class="number">5,969,783</td>
<td class="number">52.64</td>
<td class="number">19,289,624</td>
<td class="number">14.25</td>
<td class="number">4.15</td>
<td class="center"><a href="/item/board.naver?code=005930"><img src="https://ssl.pstatic.net/imgstock/images5/ico_debatebl2.gif" width="15" height="13" alt="토론실"></a></td>
</tr>
다음과 같이 종목마다 tr td로 표시되어있는것을 확인할수있다.
필자는 여기에서 종목명, 종목코드, 현재가, 시가총액, 상장주식수, 외국인 비율, 거래량, PER, ROE를 가져오려고 한다.
우선 필요한 라이브러리를 import 해주고, request로 해당 url에 get 요청으로 response된 text를 가져온다.
import requests
from bs4 import BeautifulSoup
import re
resp = requests.get('https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page=1')
html_data = resp.text
그 다음 beautifulsoup에 resp된 text를 넣어주고 데이터들이 table에 있기 때문에 tbody를 찾아준다.
soup = BeautifulSoup(html_data, 'html.parser')
tbody = soup.find('tbody')
stocks = []
이제 tr을 돌면서 td가 12개 이상일때만 데이터를 가져오기 위해서 다음과 같이 작성한다.
for row in tbody.find_all('tr'):
tds = row.find_all('td')
if len(tds) < 12:
continue
첫번째로 종목 코드와 종목 명은 다음과 같이 가져올 수 있다.
stock_name_tag = tds[1].find('a')
if stock_name_tag:
stock_name = stock_name_tag.text.strip()
href = stock_name_tag['href']
stock_code_match = re.search(r'code=(\d+)', href)
stock_code = stock_code_match.group(1) if stock_code_match else ''
else:
stock_name = ''
stock_code = ''
a tag에 해당 데이터가 있기 때문에 먼저 a를 찾아준다.
이름은 a tag의 text를 사용하면 가져올 수 있다.
code는 href속에 <a href="/item/board.naver?code=042700"> 다음과 같이 있기때문에 href를 가져온다음에 re를 이용하여 code만 가져온다.
current_price = tds[2].text.strip().replace(',', '')
market_cap = tds[6].text.strip().replace(',', '')
num_shares = tds[7].text.strip().replace(',', '')
foreign_ratio = tds[8].text.strip().replace(',', '')
volume = tds[9].text.strip().replace(',', '')
per = tds[10].text.strip()
roe = tds[11].text.strip()
나머지 필요한 값들은 td들의 위치들을 계산해서 해당 index로 가져온다음 strip을 통해 공백을 제거해주고 불필요한 단위수 구분자 ,를 제거해준다.
stock_data = {
'종목명': stock_name,
'종목코드': stock_code,
'현재가': current_price,
'시가총액': market_cap,
'상장주식수': num_shares,
'외국인비율': foreign_ratio,
'거래량': volume,
'PER': per,
'ROE': roe
}
stocks.append(stock_data)
마지막으로 stock_data 딕셔너리를 만들어줘서 해당값들을 넣어주고 stocks list에 집어 넣어준다.
이제 최종적으로 코드를 돌려보면 다음과 같은 결과가 나온다.
{'종목명': '삼성전자', '종목코드': '005930', '현재가': '58300', '시가총액': '3480383', '상장주식수': '5969783', '외국인비율': '52.64', '거래량': '22327882', 'PER': '14.25', 'ROE': '4.15'}
{'종목명': 'SK하이닉스', '종목코드': '000660', '현재가': '196600', '시가총액': '1431253', '상장주식수': '728002', '외국인비율': '54.68', '거래량': '3430724', 'PER': '57.28', 'ROE': '-15.61'}
{'종목명': 'LG에너지솔루션', '종목코드': '373220', '현재가': '415500', '시가총액': '972270', '상장주식수': '234000', '외국인비율': '4.96', '거래량': '285168', 'PER': '-578.69', 'ROE': '6.36'}
{'종목명': '삼성바이오로직스', '종목코드': '207940', '현재가': '1060000', '시가총액': '754444', '상장주식수': '71174', '외국인비율': '13.43', '거래량': '49569', 'PER': '73.36', 'ROE': '9.12'}
{'종목명': '현대차', '종목코드': '005380', '현재가': '225500', '시가총액': '472234', '상장주식수': '209416', '외국인비율': '40.92', '거래량': '487799', 'PER': '4.89', 'ROE': '13.68'}
{'종목명': '셀트리온', '종목코드': '068270', '현재가': '188200', '시가총액': '408434', '상장주식수': '217021', '외국인비율': '23.02', '거래량': '260509', 'PER': '106.33', 'ROE': '5.07'}
{'종목명': '삼성전자우', '종목코드': '005935', '현재가': '49250', '시가총액': '405272', '상장주식수': '822887', '외국인비율': '74.86', '거래량': '988459', 'PER': '12.04', 'ROE': 'N/A'}
{'종목명': '기아', '종목코드': '000270', '현재가': '94900', '시가총액': '379466', '상장주식수': '399858', '외국인비율': '39.34', '거래량': '1600147', 'PER': '3.97', 'ROE': '20.44'}
{'종목명': 'KB금융', '종목코드': '105560', '현재가': '95800', '시가총액': '377000', '상장주식수': '393528', '외국인비율': '78.42', '거래량': '1082515', 'PER': '8.75', 'ROE': '8.44'}
{'종목명': 'POSCO홀딩스', '종목코드': '005490', '현재가': '348500', '시가총액': '287946', '상장주식수': '82624', '외국인비율': '28.65', '거래량': '215777', 'PER': '21.79', 'ROE': '3.18'}
{'종목명': '신한지주', '종목코드': '055550', '현재가': '55800', '시가총액': '284241', '상장주식수': '509393', '외국인비율': '61.50', '거래량': '1130682', 'PER': '6.39', 'ROE': '8.36'}
{'종목명': 'NAVER', '종목코드': '035420', '현재가': '169800', '시가총액': '273012', '상장주식수': '160785', '외국인비율': '42.72', '거래량': '232288', 'PER': '17.99', 'ROE': '4.41'}
{'종목명': '고려아연', '종목코드': '010130', '현재가': '1270000', '시가총액': '262932', '상장주식수': '20703', '외국인비율': '14.02', '거래량': '99681', 'PER': '47.70', 'ROE': '5.72'}
{'종목명': 'LG화학', '종목코드': '051910', '현재가': '338500', '시가총액': '238955', '상장주식수': '70592', '외국인비율': '34.85', '거래량': '245429', 'PER': '167.00', 'ROE': '4.20'}
{'종목명': '삼성SDI', '종목코드': '006400', '현재가': '344500', '시가총액': '236894', '상장주식수': '68765', '외국인비율': '38.13', '거래량': '347453', 'PER': '14.22', 'ROE': '11.48'}
{'종목명': '삼성물산', '종목코드': '028260', '현재가': '132700', '시가총액': '235920', '상장주식수': '177784', '외국인비율': '27.14', '거래량': '179925', 'PER': '10.89', 'ROE': '7.28'}
{'종목명': '현대모비스', '종목코드': '012330', '현재가': '251000', '시가총액': '233418', '상장주식수': '92995', '외국인비율': '40.56', '거래량': '211343', 'PER': '6.71', 'ROE': '8.73'}
{'종목명': '삼성생명', '종목코드': '032830', '현재가': '101500', '시가총액': '203000', '상장주식수': '200000', '외국인비율': '21.81', '거래량': '118155', 'PER': '8.87', 'ROE': '4.95'}
{'종목명': '메리츠금융지주', '종목코드': '138040', '현재가': '103700', '시가총액': '197777', '상장주식수': '190720', '외국인비율': '16.71', '거래량': '202086', 'PER': '9.30', 'ROE': '28.11'}
{'종목명': '포스코퓨처엠', '종목코드': '003670', '현재가': '242000', '시가총액': '187461', '상장주식수': '77463', '외국인비율': '9.58', '거래량': '377338', 'PER': '-12,100.00', 'ROE': '1.19'}
{'종목명': '하나금융지주', '종목코드': '086790', '현재가': '65100', '시가총액': '186994', '상장주식수': '287241', '외국인비율': '68.86', '거래량': '1101142', 'PER': '5.50', 'ROE': '9.01'}
{'종목명': '한화에어로스페이스', '종목코드': '012450', '현재가': '379500', '시가총액': '172980', '상장주식수': '45581', '외국인비율': '42.80', '거래량': '149122', 'PER': '68.71', 'ROE': '25.60'}
{'종목명': '삼성화재', '종목코드': '000810', '현재가': '353000', '시가총액': '167233', '상장주식수': '47375', '외국인비율': '54.09', '거래량': '47983', 'PER': '9.32', 'ROE': '12.73'}
{'종목명': 'HD현대중공업', '종목코드': '329180', '현재가': '187300', '시가총액': '166272', '상장주식수': '88773', '외국인비율': '10.59', '거래량': '195938', 'PER': '81.54', 'ROE': '0.47'}
{'종목명': '카카오', '종목코드': '035720', '현재가': '37250', '시가총액': '165215', '상장주식수': '443531', '외국인비율': '26.82', '거래량': '548860', 'PER': '-17.03', 'ROE': '-10.26'}
{'종목명': '크래프톤', '종목코드': '259960', '현재가': '344500', '시가총액': '165016', '상장주식수': '47900', '외국인비율': '41.59', '거래량': '54428', 'PER': '18.68', 'ROE': '11.16'}
{'종목명': 'LG전자', '종목코드': '066570', '현재가': '92400', '시가총액': '151211', '상장주식수': '163648', '외국인비율': '33.94', '거래량': '360759', 'PER': '15.01', 'ROE': '3.69'}
{'종목명': '한국전력', '종목코드': '015760', '현재가': '22650', '시가총액': '145405', '상장주식수': '641964', '외국인비율': '15.34', '거래량': '1483041', 'PER': '5.48', 'ROE': '-12.63'}
{'종목명': 'KT&G', '종목코드': '033780', '현재가': '110400', '시가총액': '143876', '상장주식수': '130322', '외국인비율': '44.43', '거래량': '94177', 'PER': '14.29', 'ROE': '9.76'}
{'종목명': '두산에너빌리티', '종목코드': '034020', '현재가': '21300', '시가총액': '136440', '상장주식수': '640561', '외국인비율': '22.32', '거래량': '9908746', 'PER': '85.89', 'ROE': '0.78'}
{'종목명': 'HD한국조선해양', '종목코드': '009540', '현재가': '191000', '시가총액': '135177', '상장주식수': '70773', '외국인비율': '31.74', '거래량': '238164', 'PER': '17.05', 'ROE': '2.26'}
{'종목명': 'HMM', '종목코드': '011200', '현재가': '17240', '시가총액': '129134', '상장주식수': '749039', '외국인비율': '11.15', '거래량': '721780', 'PER': '7.25', 'ROE': '4.59'}
{'종목명': 'SK스퀘어', '종목코드': '402340', '현재가': '92900', '시가총액': '125183', '상장주식수': '134750', '외국인비율': '52.48', '거래량': '254837', 'PER': '12.57', 'ROE': '-8.04'}
{'종목명': '유한양행', '종목코드': '000100', '현재가': '153200', '시가총액': '122880', '상장주식수': '80209', '외국인비율': '20.92', '거래량': '2140190', 'PER': '83.17', 'ROE': '6.74'}
{'종목명': 'HD현대일렉트릭', '종목코드': '267260', '현재가': '340500', '시가총액': '122740', '상장주식수': '36047', '외국인비율': '35.68', '거래량': '335881', 'PER': '27.42', 'ROE': '27.71'}
{'종목명': 'SK텔레콤', '종목코드': '017670', '현재가': '57000', '시가총액': '122430', '상장주식수': '214790', '외국인비율': '42.53', '거래량': '254247', 'PER': '10.63', 'ROE': '9.63'}
{'종목명': 'LG', '종목코드': '003550', '현재가': '76700', '시가총액': '120650', '상장주식수': '157301', '외국인비율': '35.07', '거래량': '100257', 'PER': '12.21', 'ROE': '4.89'}
{'종목명': '우리금융지주', '종목코드': '316140', '현재가': '16030', '시가총액': '119037', '상장주식수': '742592', '외국인비율': '45.46', '거래량': '5249534', 'PER': '4.41', 'ROE': '8.30'}
{'종목명': 'SK이노베이션', '종목코드': '096770', '현재가': '121300', '시가총액': '116127', '상장주식수': '95736', '외국인비율': '22.24', '거래량': '348176', 'PER': '-333.24', 'ROE': '1.22'}
{'종목명': '기업은행', '종목코드': '024110', '현재가': '14430', '시가총액': '115069', '상장주식수': '797426', '외국인비율': '15.14', '거래량': '956560', 'PER': '4.30', 'ROE': '8.79'}
{'종목명': '삼성에스디에스', '종목코드': '018260', '현재가': '147100', '시가총액': '113823', '상장주식수': '77378', '외국인비율': '19.29', '거래량': '88801', 'PER': '16.13', 'ROE': '8.22'}
전체 코드는 다음과 같다.
import requests
from bs4 import BeautifulSoup
import re
resp = requests.get('https://finance.naver.com/sise/sise_market_sum.naver?sosok=0&page=1')
html_data = resp.text
soup = BeautifulSoup(html_data, 'html.parser')
tbody = soup.find('tbody')
stocks = []
for row in tbody.find_all('tr'):
tds = row.find_all('td')
if len(tds) < 12:
continue
stock_name_tag = tds[1].find('a')
if stock_name_tag:
stock_name = stock_name_tag.text.strip()
href = stock_name_tag['href']
stock_code_match = re.search(r'code=(\d+)', href)
stock_code = stock_code_match.group(1) if stock_code_match else ''
else:
stock_name = ''
stock_code = ''
current_price = tds[2].text.strip().replace(',', '')
market_cap = tds[6].text.strip().replace(',', '')
num_shares = tds[7].text.strip().replace(',', '')
foreign_ratio = tds[8].text.strip().replace(',', '')
volume = tds[9].text.strip().replace(',', '')
per = tds[10].text.strip()
roe = tds[11].text.strip()
stock_data = {
'종목명': stock_name,
'종목코드': stock_code,
'현재가': current_price,
'시가총액': market_cap,
'상장주식수': num_shares,
'외국인비율': foreign_ratio,
'거래량': volume,
'PER': per,
'ROE': roe
}
stocks.append(stock_data)
for stock in stocks:
print(stock)
다음 글에서는 이제 한페이지만 가져왔기 때문에 전체 페이지와, 코스피 코스닥 구분을 넣어서 전체 데이터셋을 만드는 코드까지 연결해보겠다.
도움이 되셨다면 공감과 댓글 부탁드립니다.
다음글 보러가기 https://dev-guardy.tistory.com/118
'ETC > Python' 카테고리의 다른 글
JQuery Ajax Post 파이썬으로 구현하기 (0) | 2024.11.05 |
---|---|
네이버 증권 파이썬(Python)을 이용하여 주식 정보 크롤링하기(Request, BeautifulSoup) 2편 (2) | 2024.10.28 |
파이썬 UUID 생성(uuid) 방법 How to generate uuid in python code (0) | 2024.10.22 |
(Python) 웹 페이지 모든 이미지 로컬 PC에 저장하기(BS4, Request, Image) (0) | 2024.10.18 |
CryptoJS AES Encrypt Python Version (2) | 2024.10.16 |