Julia언어로 '상장 법인 정보'를 획득하는 기능을 작성해봤다.

 

소스 코드는 다음 함수 3개로 되어 있다.

- f상장_법인_정보() : KRX 웹사이트에서 상장 법인 정보를 추출하는 함수.

- csv저장_법인_정보() : f상장_법인_정보()로 얻은 데이터를 CSV파일로 저장.

- csv읽기_법인_정보() : 저장된 CSV파일을 불러옴.

 

------------------------------

using Dates
using InlineStrings
using DataFrames
using TypedTables
using HTTP
using Gumbo
using Cascadia
using StringEncodings
using CSV


# KRX 웹사이트에서 상장 법인 정보를 얻는 함수.
function f상장_법인_정보()::Table
    상장_법인_정보 = DataFrame(
        종목코드=String7[], # 종목코드는 길이가 일정하므로, 고정폭 문자열 자료형 사용.
        회사명=String[],
        업종=String[],
        주요제품=String[],
        상장일=Date[],
        결산월=UInt8[])

    # KRX 상장 법인 정보 URL
    url = "https://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13"
    응답값 = HTTP.get(url)
    응답_문자열 = StringEncodings.decode(응답값.body, "EUC-KR") # EUC-KR인코딩을 UTF-8인코딩으로 변환

    # Gumbo.jl을 이용해서 HTML 파싱.
    문서 = parsehtml(응답_문자열)

    # Cascadia.jl을 사용해서 테이블의 행을 추출.
    rows = eachmatch(Selector("body > table > tbody > tr"), 문서.root)

    # 각각의 행(tr)에서 정보를 추출하는 반복문.
    for tr in rows
        cols = eachmatch(Selector("td"), tr)

        회사명 = ""
        종목코드 = ""
        업종 = ""
        주요제품 = ""
        상장일 = Date(0)
        결산월 = 0

        for (열, td) in enumerate(cols)
            문자열 = strip(text(td))  # 공백 문자 제거

            if 열 == 1
                회사명 = 문자열
            elseif 열 == 2
                종목코드 = 문자열
            elseif 열 == 3
                업종 = 문자열
            elseif 열 == 4
                주요제품 = 문자열
            elseif 열 == 5
                try
                    상장일 = Date(문자열, "yyyy-mm-dd")
                catch e
                    println("상장일 에러 : $(종목코드) '$문자열'")
                end
            elseif 열 == 6
                결산월 = tryparse(UInt8, match(r"\d+", 문자열).match)
            end
        end

        if !isempty(종목코드) && !isempty(회사명) && !isempty(업종) && 상장일 != Date(0)
            push!(상장_법인_정보, Dict(
                :종목코드 => 종목코드,
                :회사명 => 회사명,
                :업종 => 업종,
                :주요제품 => 주요제품,
                :상장일 => 상장일,
                :결산월 => 결산월))
        end
    end

    # println("행 수량 : $(length(rows))")
    println("법인정보 수량 : $(nrow(상장_법인_정보))")

    # Type-stable TypedTables.jl형태로 반환.
    # 어쩌면 그냥 DataFrame을 그대로 쓰는 게 나을런지도.
    return Table(상장_법인_정보)
end

function csv저장_법인_정보()
    CSV.write("krx_ticker.csv", f상장_법인_정보())
end

function csv읽기_법인_정보()::Table
    return CSV.read("krx_ticker.csv", Table, types=Dict(1 => String, 5 => Date, 6 => UInt8))
end

# f상장_법인_정보()
# csv저장_법인_정보()
# csv읽기_법인_정보()