ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 주식 정보 크롤링 및 필터링
    Programing/Python 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

    댓글

Designed by Tistory.