업비트 과거 거래 기록 크롤링

Updated:

1. 코인 이름 크롤링

처음에는 Selenium을 활용해서 직접 사이트에 들어가서 html 태그 찾아서 크롤링하는 방법으로 진행해보려고 했다. 근데 업비트 사이트 보안 문제인지 잘 모르겠지만 사이트에 접속이 되지를 않아서 구글링을 하던 도중 업비트 API 사이트를 통해 쉽게 이름을 크롤링 할 수 있었다.

import requests
from pandas import DataFrame
import pandas as pd

def call_coin():
    #coin 종류 가져오기
    databox=[]
    url = 'https://api.upbit.com/v1/market/all'
    response = requests.get(url)
    datas = response.json()
    # 데이터 프레임으로 변경
    df = pd.DataFrame(datas)
    # market 기준 한화로 변경
    coins_krw = df[df['market'].str.startswith('KRW')].reset_index(drop=True)
    num_index = len(coins_krw.index)
    for i in range(0, num_index):
        empty = [coins_krw.iloc[i,0],coins_krw.iloc[i,2]]
        databox.append(empty)
    return databox

2. 2월달 코인 거래 1분봉 데이터 크롤링

과거 코인 데이터 크롤링에 사용했던 코드를 활용해서 for문을 추가해줬다. 사이트 상에서 한 번에 가져올 수 있는 데이터가 200개라서 for문을 잘 설정해서 데이터를 모아야했다.

1분 봉으로 데이터를 추출할 예정이기 때문에 한 번에 60개씩 데이터를 추출해서 최대한 카운팅을 맞춰보려고 노력했다. 처음 시범 데이터를 추출했을 때 총 40,320개의 데이터가 나와야하는데 BTC 기준 39,829개가 나오길래 사이사이 빈 곳을 어떻게 처리해야할지 고민이 됬다.

혹시 점검 시간이 고려되었을 가능성을 생각해서 추가로 ETHNEO 데이터를 비교해봤는데 아래 두 가지 방법 모두 같은 개수로 나와가지고 공식 API는 하다보니까 너무 많은 요청이 들어오면 에러가 발생해서 비공식 API로 알려진 방법을 활용했다.

공식 API

for coin in coin_names:
    box = {}
    for day in days:
        for hour in hours:
            url = "https://api.upbit.com/v1/candles/minutes/1"

            querystring = {"market": coin[0], "to": "2021-02-"+day+" "+hour+":00:00", "count": "60"}

            response = requests.request("GET", url, params=querystring)
            tradedata = response.json()
            sleep(0.1)

비공식 API

for coin in coin_names:
    box = {}
    for day in days:
        for hour in hours:
            r = requests.get("https://crix-api-endpoint.upbit.com/v1/crix/candles/minutes/1?code=CRIX.UPBIT."+coin[0]+"&count=60&to=2021-02-"+day+"%20"+hour+":00:00")
            tradedata = r.json()

3. 전체 코드

전체 개수가 다 다르게 나오긴 하지만 API의 문제로 생각되서 둘 중 어느 방법을 활용하던 같은 결과가 나와서 일단 그대로 사용하기로 했다. 가격의 변동성에서 패턴을 읽는 과정에는 크게 어려움이 없다고 일단은 생각하고 진행하기로 했다.

추후 찾아보니까 거래량이 부족한 경우 1분 봉이 형성이 안되서 데이터 개수가 모자른 경우가 발생하는 것 같다.

마지막으로 완성한 전체 코드는 아래 첨부한다.

import requests
import pandas as pd
from time import sleep

def call_coin():
    #coin 종류 가져오기
    databox=[]
    url = 'https://api.upbit.com/v1/market/all'
    response = requests.get(url)
    datas = response.json()
    # 데이터 프레임으로 변경
    df = pd.DataFrame(datas)
    # market 기준 한화로 변경
    coins_krw = df[df['market'].str.startswith('KRW')].reset_index(drop=True)
    num_index = len(coins_krw.index)
    for i in range(0, num_index):
        empty = [coins_krw.iloc[i,0],coins_krw.iloc[i,2]]
        databox.append(empty)
    return databox

days = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24', '25', '26', '27', '28']
hours = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12', '13', '14', '15', '16', '17', '18', '19', '20', '21', '22', '23', '24']

coin_names=call_coin()

for coin in coin_names:
    box = {}
    for day in days:
        for hour in hours:
            r = requests.get("https://crix-api-endpoint.upbit.com/v1/crix/candles/minutes/1?code=CRIX.UPBIT."+coin[0]+"&count=60&to=2021-02-"+day+"%20"+hour+":00:00")
            tradedata = r.json()

            for trade in reversed(tradedata):
                time = trade['candleDateTime']
                timedata = time[0:10] + " " + time[11:16]
                op = trade['openingPrice']  # op 는 시작 가격
                tp = trade['tradePrice']  # tp 는 종가
                lp = trade['lowPrice']  # lp 는 저가
                hp = trade['highPrice']  # hp 는 고가
                box[timedata] = [op, tp, hp, lp]

    tradedata = pd.DataFrame(box)
    tradedata.rename(index={0: "Open Price", 1: "High Price", 2: "Low Price", 3: 'Close Price'}, inplace=True)
    transposed_tradedata = tradedata.transpose()
    transposed_tradedata.to_excel(excel_writer='C:/Users/whdtlr/Bitcoin_desktop/coins/'+coin[1]+'.xlsx')
    sleep(1)

현재 이렇게 크롤링 진행하면 request 함수에 오류가 발생하고 있다. 아마도 너무 많은 요청이 들어가서 오류가 발생한 것이라고 생각해서 sleep 함수를 활용해서 해결해보려 하고 있다.