본문 바로가기

코드 끄적임

포켓몬 리스트 받아와서 엑셀화

api사용법을 까먹을것 같아서 코드를 perplexity와 함께 짬

비동기처리 방법에 대해 이론을 알지만 라이브러리를 추천받기 위해 ai 사용

import asyncio
import aiohttp

async def fetch_species(session, url):
    async with session.get(url) as response:
        return await response.json()

async def fetch_pokemon_korean_name(session, species_url):
    species_data = await fetch_species(session, species_url)
    # data['names'][2]['name']에 한국어 이름 있다고 가정
    try:
        korean_name = species_data['names'][2]['name']
    except (IndexError, KeyError):
        korean_name = None
    return korean_name

async def fetch_pokemon_list(session, url):
    async with session.get(url) as response:
        return await response.json()

async def main():
    base_url = 'https://pokeapi.co/api/v2/pokemon-species/'
    limit = 100
    offset = 0
    total_to_fetch = 500
    korean_names = []

    async with aiohttp.ClientSession() as session:
        while len(korean_names) < total_to_fetch:
            list_url = f'{base_url}?offset={offset}&limit={limit}'
            data = await fetch_pokemon_list(session, list_url)
            species_urls = [item['url'] for item in data['results']]
            tasks = [fetch_pokemon_korean_name(session, url) for url in species_urls]
            results = await asyncio.gather(*tasks)
            korean_names.extend([name for name in results if name])
            offset += limit
            if not data['next']:
                break

    korean_names = korean_names[:total_to_fetch]

    for i, name in enumerate(korean_names, 1):
        print(f'{i}. {name}')

# 스크립트로 실행 시 아래 주석 해제
# asyncio.run(main())

엑셀화 하기 코드 추가
korean_names.extend([name for name in results if name]) 이 부분에서 리스트에 바로 딕셔너리 데이터를 넣고싶었으나
'https://pokeapi.co/api/v2/pokemon-species/{num}'
페이징 방식으로 코드가 구현되어 있어서 num을 어떻게 접근할까 고민 중 일단 결과를 내기 위해

pokemon_list = []
    for i, name in enumerate(korean_names, start=1):
        pokemon_list.append({
            'No.': i,
            '포켓몬명': name,
            '동료여부': '',
            '도구1': '',
            '도구2': '',
            '도구3': ''
        })
    print(pokemon_list)
    df = pd.DataFrame(pokemon_list)
    df.to_excel('pokemon_checklist.xlsx', index=False)

을 main 함수 안에 추가
결과는 도출
Ai에게 방법을 물어봤을 때

start_index = len(korean_names) + 1
dicts_to_add = [
    {
         'No.': start_index + idx,
         '포켓몬명': name,
         '동료여부': '',
         '도구1': '',
         '도구2': '',
        '도구3': ''
    }
    for idx, name in enumerate(results) if name
]
korean_names.extend(dicts_to_add)

추가하라고 말했음.

  1. 여기서 enumerate는 내가 파이썬 배울때 썼던것이 아니라 따로 공부가 필요했음. 대략 무결성을 검증하기 위한 함수인듯
    [(idx, name) for idx, name in enumerate(results) if name] 이렇게 쓰는 듯 함
    문법은 조금 생소하지만 좋은 내장함수를 배운것 같다.
  2. start_index를 책정하는 방식이 계속 길이를 재고 거기서 1을 더 해가는 방식을 추천
    -> 계속 길이를 함수로 하고 +1 씩 하면 데이터가 백억개 이상일 경우 유의미한 문제가 생기지 않을까 생각함
     -> 그냥 숫자가 1씩만 오르면 되지 않을까? 생각
    start_index = 0
      async with aiohttp.ClientSession() as session:
         while len(korean_names) < total_to_fetch:
             ...
             start_index += 1
             ...
    이런식이면 좋지 않을까 생각했음. 하지만 결과가 안 좋음.
    이유가 뭘까 디버깅 했을 때
    비동기 처리가 이루어져서 results에 이미 limit의 값만큼 들어가 있어서 1번 처리되는것인데 동기처리식으로 생각했기 때문
    while문이 많이 돌아가지 않아서 start_index는 하나씩밖에 안 오르기 때문에 정확성을 위해 계속 len() 함수를 써야했음