코인 심볼 이미지 가져오는 문제

황석범·2025년 1월 29일
0

내일배움캠프_iOS_5기

목록 보기
70/76

현재 진행 중인 프로젝트에서 각 거래소 openAPI에서 현재 시세 정보, 차트를 그리기 위한 캔들 데이터와 같은 데이터들을 받아온다. 하지만 코인의 심볼 이미지 아래와 같은 이미지는 각 거래소 API에서 제공하지 않아 외부 API를 통해 이미지 URL을 가져오려고 했다. 하지만 요청 수 제한에 걸려 가지고 오지 못하게 되었다.


문제 분석

당연히 가져와질 것이라고 생각하고 이미지는 새로 요청할 필요가 없으니까(이미지가 변할 경우는 거의 없으므로) 매번 이미지를 요청하지 않을 방법을 생각 중이었다... 이미지를 한 번만 가져오고 이후에는 캐싱된 데이터를 활용할 방법을 찾고 있었는데


해결 방법 찾기

  1. 이미지 요청을 나눠서 한다

이미지만 요청을 나눠서 할 순 없으니 코인 시세 데이터를 가져올 때 화면 단위로 스크롤할 때 마다 요청해서 가져오기 ( 무한 스크롤 같이 )

  1. 앱 번들에 미리 정의된 심볼 이미지 매핑해서 사용하기

그냥 Assets 파일과 같은 로컬에 이미지를 저장해놓고 사용하기...


해결 방향

  1. 앱 번들에 미리 정의된 심볼 이미지 매핑해서 사용하기

2번을 선택하고 저장된 이미지가 없거나 새로 추가되어야 하는 경우만 URL을 요청해서 사용하는 방법으로 가야할 것 같다.


1. PNG 이미지 파일을 저장하기 위해 원래 가져오려고 했던 API의 이미지 URL을 뽑아와보자

import requests
import time

# 기존 coin_images 딕셔너리
coin_images = {
    "bitcoin": "https://coin-images.coingecko.com/coins/images/1/thumb/bitcoin.png?1696501400",
    "ethereum": "https://coin-images.coingecko.com/coins/images/279/thumb/ethereum.png?1696501400",
    "ripple": "https://coin-images.coingecko.com/coins/images/44/thumb/ripple.png?1696501400",
}

# CoinGecko API에서 추가할 코인 리스트
coin_ids = [
    "0x", "egld", "aave", "adappter-token", "aelf", "aergo", "amo", "ankr", "apm-coin",
    "arpa-chain", "balancer", "basic-attention-token", "bella-protocol", "bitcoin",
    "bitcoin-cash", "bitcoin-gold", "bitcoin-sv", "bora", "bosagora", "cardano", "chainlink",
    "chromia", "civic", "compound", "contentos", "cortex", "creditcoin", "crypto-com-chain",
    "electric-vehicle-zone", "elrond", "enjincoin", "eos", "ethereum", "ethereum-classic",
    "firmachain", "fit-token", "function-x", "golem", "hive", "icon", "iexec-rlc", "iost",
    "kyber-network", "loom-network", "loopring", "metal", "meverse", "mixmarvel", "moviebloc",
    "nervos-network", "nestree", "numeraire", "observer", "orbs", "polkadot", "power-ledger",
    "proton", "qtum", "quiztok", "reserve-rights-token", "ripple", "status", "steem",
    "stp-network", "swipe", "the-sandbox", "theta-fuel", "theta-token", "tron", "ultra", "uma",
    "uniswap", "valor-token", "vechain", "waves", "wax", "wom-token", "yearn-finance", "zilliqa"
]

# CoinGecko API 엔드포인트
api_base_url = "https://api.coingecko.com/api/v3/coins/"

# API 요청 및 이미지 URL 가져오기
for coin_id in coin_ids:
    url = f"{api_base_url}{coin_id.lower()}"
    try:
        response = requests.get(url, timeout=10)  # 타임아웃 설정 (10초)
        if response.status_code == 200:
            data = response.json()
            image_url = data.get("image", {}).get("thumb", "")
            if image_url:
                coin_images[coin_id.lower()] = image_url
                print(f"✅ {coin_id} 이미지 추가: {image_url}")
        else:
            print(f"❌ {coin_id} 가져오기 실패: {response.status_code}")
    except requests.exceptions.RequestException as e:
        print(f"⚠️ {coin_id} 가져오는 중 오류 발생: {e}")
    
    # API Rate Limit 방지 (CoinGecko는 초당 10개 요청 제한)
    time.sleep(15)

# 최종 결과 출력
print("\n📌 최종 coin_images 딕셔너리:")
print(coin_images)

python으로 작성된 스크립트를 통해 URL 딕셔너리를 만들어 주었다.
15초 마다 요청해서 천천히 뽑아오고 밥을 먹고 왔다...

📌 최종 coin_images 딕셔너리:
{'bitcoin': 'https://coin-images.coingecko.com/coins/images/1/thumb/bitcoin.png?1696501400', 'ethereum': 'https://coin-images.coingecko.com/coins/images/279/thumb/ethereum.png?1696501628', 'ripple': 'https://coin-images.coingecko.com/coins/images/44/thumb/xrp-symbol-white-128.png?1696501442', '0x': 'https://coin-images.coingecko.com/coins/images/863/thumb/0x.png?1696501996', 'aave': 'https://coin-images.coingecko.com/coins/images/12645/thumb/aave-token-round.png?1720472354', 'adappter-token': 'https://coin-images.coingecko.com/coins/images/14203/thumb/logo_on.png?1696513920', 'aelf': 'https://coin-images.coingecko.com/coins/images/1371/thumb/aelf-logo.png?1696502429', 'aergo': 'https://coin-images.coingecko.com/coins/images/4490/thumb/aergo.png?1696505079', 'amo': 'https://coin-images.coingecko.com/coins/images/4009/thumb/amo-logomark_black.png?1696504648', 'ankr': 'https://coin-images.coingecko.com/coins/images/4324/thumb/U85xTl2.png?1696504928', 'apm-coin': 'https://coin-images.coingecko.com/coins/images/10069/thumb/PvDCvh5h_400x400.png?1696510100', 'balancer': 'https://coin-images.coingecko.com/coins/images/11683/thumb/Balancer.png?1696511572', 'basic-attention-token': 'https://coin-images.coingecko.com/coins/images/677/thumb/basic-attention-token.png?1696501867', 'bella-protocol': 'https://coin-images.coingecko.com/coins/images/12478/thumb/Bella.png?1696512296', 'bitcoin-cash': 'https://coin-images.coingecko.com/coins/images/780/thumb/bitcoin-cash-circle.png?1696501932', 'bitcoin-gold': 'https://coin-images.coingecko.com/coins/images/1043/thumb/bitcoin-gold-logo.png?1696502150', 'bora': 'https://coin-images.coingecko.com/coins/images/7646/thumb/mqFw8hxm_400x400.jpeg?1696507900', 'bosagora': 'https://coin-images.coingecko.com/coins/images/9202/thumb/Picture1.png?1696509320', 'cardano': 'https://coin-images.coingecko.com/coins/images/975/thumb/cardano.png?1696502090', 'chainlink': 'https://coin-images.coingecko.com/coins/images/877/thumb/chainlink-new-logo.png?1696502009', 'civic': 'https://coin-images.coingecko.com/coins/images/788/thumb/civic-orange.png?1696501939', 'contentos': 'https://coin-images.coingecko.com/coins/images/8379/thumb/4036.png?1696508571', 'cortex': 'https://coin-images.coingecko.com/coins/images/3861/thumb/2638.png?1696504523', 'crypto-com-chain': 'https://coin-images.coingecko.com/coins/images/7310/thumb/cro_token_logo.png?1696507599', 'electric-vehicle-zone': 'https://coin-images.coingecko.com/coins/images/9456/thumb/kLohzILUIln6mHFYOlecpWjINVIH-BVghP2vRTeuD0XteaQa7Lpn4sLcuPN4gHw8MU2pKWZCJRNwBmyyl1CYxplCLDcgSVihMC7vvfmkepY-_O_ImWBA27s4pKNlhcBnBYrc8y5WH0ZB2CjmqPh-32nPslrv329tqFWr2DAR8dl4R5LZGgeZ1ubCdtMoUua6gEL3umYShHBxrYLto.jpg?1696509547', 'enjincoin': 'https://coin-images.coingecko.com/coins/images/1102/thumb/Symbol_Only_-_Purple.png?1709725966', 'eos': 'https://coin-images.coingecko.com/coins/images/738/thumb/CG_EOS_Icon.png?1731705232', 'ethereum-classic': 'https://coin-images.coingecko.com/coins/images/453/thumb/ethereum-classic-logo.png?1696501717', 'firmachain': 'https://coin-images.coingecko.com/coins/images/9892/thumb/6mHcLurm_400x400.jpg?1696509941', 'golem': 'https://coin-images.coingecko.com/coins/images/542/thumb/Golem_Submark_Positive_RGB.png?1696501761', 'hive': 'https://coin-images.coingecko.com/coins/images/10840/thumb/logo_transparent_4x.png?1696510797', 'icon': 'https://coin-images.coingecko.com/coins/images/1060/thumb/ICON-symbol-coingecko_latest.png?1706638336', 'iexec-rlc': 'https://coin-images.coingecko.com/coins/images/646/thumb/pL1VuXm.png?1696501840', 'kyber-network': 'https://coin-images.coingecko.com/coins/images/947/thumb/logo-kncl.png?1696502063', 'loom-network': 'https://coin-images.coingecko.com/coins/images/3387/thumb/1_K76UVoLq-FOL7l-_Fag-Qw_2x.png?1696504085', 'loopring': 'https://coin-images.coingecko.com/coins/images/913/thumb/LRC.png?1696502034', 'metal': 'https://coin-images.coingecko.com/coins/images/763/thumb/Metal.png?1696501916', 'meverse': 'https://coin-images.coingecko.com/coins/images/24566/thumb/0sp1DWVw_400x400.png?1696523742', 'mixmarvel': 'https://coin-images.coingecko.com/coins/images/8222/thumb/8878caf93b1e3b6cfb3b414bda3b5250.png?1696508428', 'moviebloc': 'https://coin-images.coingecko.com/coins/images/8460/thumb/MBL_Logo.png?1696508646', 'nervos-network': 'https://coin-images.coingecko.com/coins/images/9566/thumb/Nervos_White.png?1696509646', 'nestree': 'https://coin-images.coingecko.com/coins/images/9362/thumb/nestree.png?1696509461', 'numeraire': 'https://coin-images.coingecko.com/coins/images/752/thumb/numeraire.png?1696501906', 'orbs': 'https://coin-images.coingecko.com/coins/images/4630/thumb/Orbs.jpg?1696505200', 'polkadot': 'https://coin-images.coingecko.com/coins/images/12171/thumb/polkadot.png?1696512008', 'power-ledger': 'https://coin-images.coingecko.com/coins/images/1104/thumb/Powerledger_Northstar_colour_digital_%282%29.png?1706702222', 'proton': 'https://coin-images.coingecko.com/coins/images/10941/thumb/XPR.jpg?1696510891', 'qtum': 'https://coin-images.coingecko.com/coins/images/684/thumb/Qtum_Logo_blue_CG.png?1696501874', 'quiztok': 'https://coin-images.coingecko.com/coins/images/8208/thumb/QTCON.png?1696508415', 'reserve-rights-token': 'https://coin-images.coingecko.com/coins/images/8365/thumb/RSR_Blue_Circle_1000.png?1721777856', 'status': 'https://coin-images.coingecko.com/coins/images/779/thumb/status.png?1696501931', 'steem': 'https://coin-images.coingecko.com/coins/images/398/thumb/steem.png?1696501691', 'stp-network': 'https://coin-images.coingecko.com/coins/images/8713/thumb/STP.png?1696508875', 'swipe': 'https://coin-images.coingecko.com/coins/images/9368/thumb/swipe.png?1696509466', 'the-sandbox': 'https://coin-images.coingecko.com/coins/images/12129/thumb/sandbox_logo.jpg?1696511971', 'theta-fuel': 'https://coin-images.coingecko.com/coins/images/8029/thumb/1_0YusgngOrriVg4ZYx4wOFQ.png?1696508251', 'theta-token': 'https://coin-images.coingecko.com/coins/images/2538/thumb/theta-token-logo.png?1696503349', 'tron': 'https://coin-images.coingecko.com/coins/images/1094/thumb/tron-logo.png?1696502193', 'ultra': 'https://coin-images.coingecko.com/coins/images/4480/thumb/Ultra.png?1696505069', 'uma': 'https://coin-images.coingecko.com/coins/images/10951/thumb/UMA.png?1696510900', 'uniswap': 'https://coin-images.coingecko.com/coins/images/12504/thumb/uniswap-logo.png?1720676669', 'vechain': 'https://coin-images.coingecko.com/coins/images/1167/thumb/VET_Token_Icon.png?1710013505', 'waves': 'https://coin-images.coingecko.com/coins/images/425/thumb/waves.png?1696501700', 'wax': 'https://coin-images.coingecko.com/coins/images/1372/thumb/WAX_Coin_Tickers_P_512px.png?1696502430', 'wom-token': 'https://coin-images.coingecko.com/coins/images/4559/thumb/wom_logo_small.png?1696505139', 'yearn-finance': 'https://coin-images.coingecko.com/coins/images/11849/thumb/yearn.jpg?1696511720', 'zilliqa': 'https://coin-images.coingecko.com/coins/images/2687/thumb/Zilliqa-logo.png?1696503475'}

2. PNG 파일로 저장하기


import os
import requests

# 저장할 이미지 목록
coin_images = {
    "bitcoin": "https://coin-images.coingecko.com/coins/images/1/thumb/bitcoin.png?1696501400",
    "ethereum": "https://coin-images.coingecko.com/coins/images/279/thumb/ethereum.png?1696501400",
    "ripple": "https://coin-images.coingecko.com/coins/images/44/thumb/ripple.png?1696501400",
    # 추가하고 싶은 코인 이미지 URL을 여기에 넣으세요.
}

# 저장할 폴더 생성
save_path = os.path.expanduser("~/Desktop/coin_images")  # 데스크탑에 저장
os.makedirs(save_path, exist_ok=True)

# 이미지 다운로드
for coin, url in coin_images.items():
    response = requests.get(url, stream=True)
    if response.status_code == 200:
        with open(os.path.join(save_path, f"{coin}.png"), "wb") as file:
            for chunk in response.iter_content(1024):
                file.write(chunk)
        print(f"✅ {coin}.png 다운로드 완료")
    else:
        print(f"❌ {coin}.png 다운로드 실패")

print("모든 이미지 다운로드 완료!")


파일을 잘..? 가져왔다... 이게 맞는지 모르겠다...

profile
iOS 공부중...

0개의 댓글

관련 채용 정보