Programing/Python

주식 정보 크롤링 및 필터링

mjune.kim 2023. 3. 3. 15:05

아래 코드는 나도코딩님의 유투브 강좌를 참고하였다. 웹사이트로 부터 크롤링을 통해 데이터를 긁어온 후 데이터를 조건에 맞게 Filtering 을 적용해 보았다.

https://youtu.be/ZDh1C7qw0Rs

예제에서는 총 3가지 필드, '영업이익', '자산총계', '매출액' 를 읽어오지만, 나는 ['거래량', '외국인비율', 'PER', 'ROE', 'ROA', 'PBR'] 를 읽어 왔다.

[크롤링코드]

## pip install pandas, selenium, lxml
import pandas as pd
from selenium import webdriver
from selenium.webdriver.common.by import By
import os

browser = webdriver.Chrome()
browser.maximize_window() # 창 최대화

#1. 페이지 이동
KOSPI = False
if KOSPI:
    url = "https://finance.naver.com/sise/sise_market_sum.naver?&page="
else:
    url = "https://finance.naver.com/sise/sise_market_sum.naver?sosok=1&page="
browser.get(url)

#2. 조회학목 초기화 (체크되어 이쓴ㄴ 항목 체크 해제)
checkboxes = browser.find_elements(By.NAME, 'fieldIds')
for checkbox in checkboxes:
    if checkbox.is_selected(): ## 체크되어 있는지 확인
        checkbox.click() ## 클릭 해제
        
#3. 조회 항목 선택
#items_to_select = ['영업이익', '자산총계', '매출액']
items_to_select = ['거래량', '외국인비율', 'PER', 'ROE', 'ROA', 'PBR']
## 부모 -> 형제
for checkbox in checkboxes:
    parent = checkbox.find_element(By.XPATH, '..') ## 부모 element
    label = parent.find_element(By.TAG_NAME, 'label')
    #print (label.text)
    if label.text in items_to_select:
        checkbox.click() ## 클릭 해제
        
        
#4. 적용하기 클릭
## XPath: //*[@id="contentarea_left"]/div[2]/form/div/div/div
##"javascript:fieldSubmit()"
btn_apply = browser.find_element(By.XPATH, '//a[@href="javascript:fieldSubmit()"]')
btn_apply.click()


for idx in range(1, 40): ## 1~40
    #사전작업 : 페이지 이동
    browser.get(url + str(idx)) ## http://naver.com...?page=1
    
    #5. 데이터 추출
    df = pd.read_html(browser.page_source)[1]
    if len(df) == 0: ## 더이상 가져올 반복문이 없는 경우
        break
    
    df.dropna(axis='index', how='all', inplace=True) ## 줄기준 삭제 / 줄 전체가 NaN 일 경우
    df.dropna(axis='columns', how='all', inplace=True) ## 줄기준 삭제 / 줄 전체가 NaN 일 경우


    #6. 파일 저장
    if KOSPI == True:
        f_name = 'sise_cospi.csv'
    else:
        f_name = 'sise_kosdac.csv'
    if os.path.exists(f_name): ## 파일이 있다면 해더 부분 제외
        df.to_csv(f_name, encoding='utf-8-sig', index=False, mode='a', header=False) # 한글 설정
    else:
        df.to_csv(f_name, encoding='utf-8-sig', index=False) # 한글 설정


    print (f"{idx} page complete!!")

browser.quit()

 

[필터링 조건]

1. PBR < 0.7

2. ROE - ROA < 5% (부채 비율이 작을것)

3. PER 내림 차순 - 영업이익에 비해 주가가 낮은 종목으로 정렬한다.

[Filtering Code]

#!/usr/bin/env python
# coding: utf-8

# In[1]:


import pandas as pd

KOSPI = True
if KOSPI == True:
    df_file = "sise_kospi.csv"
else:
    df_file = "sise_kosdac.csv"
    
df = pd.read_csv(df_file)
df.head(10)
myfrac = 10 # 1 percentage selection


# In[2]:


## remove NaN at any columns
df.dropna(axis='index', how='any', inplace=True)

## Remove negative value
idx_list = ['PER', 'ROE', 'ROA', 'PBR']
[df.drop(df[df[idx] < 0].index, inplace = True) for idx in idx_list]

# If you have space in column name
# Specify column name with in single quotes
#df2 = df[df['column name']]

# Using loc
#df2 = df.loc[df["Fee"] >= 24000 ]

# Delect rows based on multiple column value
#df2 = df[ (df['Fee'] >= 22000) & (df['Discount'] == 2300)]

df.head(10)


# ### PBR should be less than 0.7