Web 크롤링/Python Crawling
네이버 증권 정보 크롤링 예제 2 - 일별 시세 정보 가져오기
Link2Me
2023. 3. 31. 00:42
728x90
최초작성 : 2023.3.31
네이버 증권에서 일별 시세 정보를 가져오는 코드이다.
아래 코드로는 100% 만족된 결과를 도출하지 못한다.
IF 조건문을 사용해서 원하는 결과를 도출하는 건 개발자의 몫이다.
또한 DB에 저장되는 순서를 날짜가 적은 데이터를 먼저 저장하기 위한 방법으로 수정하는 것이 좋다.
import requests
from fake_useragent import UserAgent
# BeautifulSoup은 HTML 과 XML 파일로부터 데이터를 수집하는 라이브러리
from bs4 import BeautifulSoup
# BeautifulSoup 에서는 Xpath 사용 불가능
import pymysql
import re
def financialSiseDayData(code,page):
ua = UserAgent()
headers = {'User-agent': ua.ie}
url = f'https://finance.naver.com/item/sise_day.naver?code={code}&page={page}'
# print(url)
res = requests.get(url, headers=headers)
#
if res.status_code == 200:
html = res.text
# HTML 페이지 파싱 BeautifulSoup(HTML데이터, 파싱방법)
soup = BeautifulSoup(html, 'html.parser')
# find() : 가장 먼저 검색되는 태그 반환
body = soup.select_one("table")
# print(body)
items = body.find_all('tr', {'onmouseover':'mouseOver(this)'})
# print(items)
conn = pymysql.connect(host="localhost", user="", password="", db="studydb", charset="utf8")
curs = conn.cursor()
for item in items:
information = item.text
info = information.split('\n')
# print(info)
# print(info[2], "type: ", type(info[2]))
# print(code, info[1],info[2],info[8],info[9],info[10],info[11],info[5].strip())
closeM = re.sub(r'[^0-9]', '', info[2])
openM = re.sub(r'[^0-9]', '', info[8])
highM = re.sub(r'[^0-9]', '', info[9])
lowM = re.sub(r'[^0-9]', '', info[10])
volume = re.sub(r'[^0-9]', '', info[11])
# 기존 DB에 있는 데이터인 경우에는 중복 저장하지 말고 무시하라.
sql = "insert ignore into stock_day (code,date,close,open, high, low, volume) values (%s, %s, %s, %s, %s, %s, %s)"
val = (str(code), info[1], closeM, openM, highM, lowM, volume)
curs.execute(sql,val)
conn.commit()
conn.close()
else:
print(res.status_code)
if __name__ == '__main__':
code = 140670
for i in range(1, 4): # 1개월 데이터만 추출
financialSiseDayData(code,str(i))
print('완료되었습니다.')
|
DB에 저장하기 위한 SQL 코드
CREATE TABLE stock_day (
idx int(11) NOT NULL,
code varchar(8) NOT NULL COMMENT '종목코드',
date char(10) NOT NULL COMMENT '날짜',
close double NOT NULL DEFAULT 0 COMMENT '종가',
open double NOT NULL DEFAULT 0 COMMENT '시가',
high double NOT NULL DEFAULT 0 COMMENT '고가',
low double NOT NULL DEFAULT 0 COMMENT '저가',
volume double NOT NULL DEFAULT 0 COMMENT '거래량',
display int(2) NOT NULL DEFAULT 1,
reg_date timestamp NOT NULL DEFAULT current_timestamp()
) ENGINE=InnoDB DEFAULT CHARSET=utf8;
ALTER TABLE stock_day
ADD PRIMARY KEY (idx),
ADD UNIQUE KEY code_date (code,date);
ALTER TABLE stock_day
MODIFY idx int(11) NOT NULL AUTO_INCREMENT;
COMMIT;
|
코드와 날짜를 UNIQUE KEY 로 설정하였다.
Updated : 2024.08.30
위 코드를 가지고 PHP simple_html_dom 라이브러리를 이용하는 코드로 변환을 시도했었다.
결과가 만족스럽지 못해서 DOM 을 분석하면서 다시 작성을 했다.
그리고 다시 ChatGTP를 이용하여 Python 코드로 변경해 달라고 했더니 좀 더 깔끔한 결과를 얻었다.
import requests
from fake_useragent import UserAgent
from bs4 import BeautifulSoup
import re
def financialSiseDayData(code,page):
ua = UserAgent()
headers = {'User-agent': ua.ie}
url = f'https://finance.naver.com/item/sise_day.naver?code={code}&page={page}'
# print(url)
res = requests.get(url, headers=headers)
#
if res.status_code == 200:
html = res.text
# HTML 페이지 파싱 BeautifulSoup(HTML데이터, 파싱방법)
soup = BeautifulSoup(html, 'html.parser')
# table = soup.select_one(".type2")
# items = table.find_all('tr', {'onmouseover':'mouseOver(this)'})
items = soup.select('.type2 tr[onmouseover="mouseOver(this)"]')
stock_day_temp = []
for item in items:
info = []
tds = item.find_all('td')
for td in tds:
info.append(td.get_text(strip=True)) # <td> 내부 텍스트를 추출하여 리스트에 저장
sdate = re.sub(r'[^0-9.]', '', info[0]) # 날짜
closeM = re.sub(r'[^0-9]', '', info[1]) # 종가
openM = re.sub(r'[^0-9]', '', info[3]) # 시가
highM = re.sub(r'[^0-9]', '', info[4]) # 고가
lowM = re.sub(r'[^0-9]', '', info[5]) # 저가
volume = re.sub(r'[^0-9]', '', info[6]) # 거래량
cv30 = float(closeM) * 1.3 # 상한가
cv60 = float(closeM) * 1.6 # 단기 투경 기준
cv100 = float(closeM) * 2 # 4주 투경 기준
stock_day_temp.append([
code, sdate, closeM, openM, highM, lowM, volume, cv30, cv60, cv100
])
for items in reversed(stock_day_temp):
print(items)
else:
print(res.status_code)
if __name__ == '__main__':
code = '039610'
for i in range(1,3,1): # 1개월 데이터만 추출
financialSiseDayData(code,str(i))
print('완료되었습니다.')
|
728x90