de mi serie de viajes de ingeniería de datos. En la primera parte, compartí mi hoja de ruta de 12 meses para la transición de analista de datos a ingeniero de datos. Aquí es donde comienza la construcción real.
Cuando publiqué mi primer artículo que documentaba mi viaje en ingeniería de datos, sucedió algo inesperado. La gente resonó con eso. Hubo extraños que se acercaron y dijeron que estaban emocionados de seguirme. Eso se sintió bien.
Pero también vino con presión.
De repente, esto ya no era sólo un objetivo personal que podía abandonar silenciosamente si las cosas se ponían difíciles. La gente estaba mirando. La gente estaba en el mismo barco. Y esa responsabilidad, sinceramente, es parte del motivo por el que estás leyendo esto ahora mismo.
Entonces tuve que mudarme. Y como cualquiera que comienza una nueva habilidad, lo primero que hice fue buscar recursos. Existen innumerables tutoriales en Internet sobre ingeniería de datos. Vídeos de YouTube, cursos, guías escritas. Más de lo que jamás podrías terminar.
Pero no podía limitarme a consumir teoría. Necesitaba construir algo. Algo real, con datos reales, que al final funcionó.
Así que cerré los tutoriales y abrí una libreta de Google Colab. Encontré la documentación de la API de GitHub y decidí que iba a crear mi primer canal ETL desde cero. Sin tomarse de la mano. Solo yo, algo de Python y un objetivo.
Este artículo es esa experiencia documentada en su totalidad. El código, la confusión, las pequeñas victorias y lo que realmente aprendí al hacerlo.
Primero, ¿qué es ETL?
Antes de entrar en lo que construí, permítanme explicarles rápidamente qué significa realmente ETL porque tuve que buscar esto yo mismo no hace mucho.
ETL significa Extraer, Transformar, Cargar. Es uno de los conceptos más fundamentales en ingeniería de datos.
Extraer significa ir a algún lugar para obtener datos. Una API, una base de datos, un sitio web, un archivo. Estás extrayendo información sin procesar de una fuente. Transformar significa limpiar y dar forma a esos datos. Eliminar filas defectuosas, agregar nuevas columnas, reestructurarlas para que sean realmente útiles. Cargar significa guardar los datos limpios en algún lugar. Una base de datos, un almacén de datos, un simple archivo CSV.
Eso es todo. Esos tres pasos, realizados en secuencia, son lo que es una canalización de datos. Todo lo demás en ingeniería de datos, Airflow, Spark, Databricks, son formas más sofisticadas de hacer esas mismas tres cosas a escala.
Estoy al comienzo de mi hoja de ruta, así que lo mantuve simple. Python puro, aún no hay herramientas de orquestación. Pero la forma del problema es la misma.
lo que construí
Extraje datos de la API de GitHub, específicamente los repositorios de Python más destacados creados en los últimos 30 días. Luego lo limpié, agregué una nueva columna y guardé el resultado como un archivo CSV.
Simple. Real. Totalmente mío.
Así es como fue.
Paso 1: extraer
Lo primero que tuve que hacer fue descubrir cómo comunicarme con la API de GitHub. Una API es básicamente una puerta que abre una empresa o plataforma para que los desarrolladores puedan solicitarle datos de forma programática, sin tener que copiar y pegar nada manualmente.
GitHub tiene una API pública y gratuita. No se necesita cuenta ni plan pago para búsquedas básicas.
Aquí está el código que escribí para extraer los datos:
URL de solicitudes de importación = “https://api.github.com/search/repositories” params = { “q”: “idioma:python creado:>2025-04-22”, “sort”: “stars”, “order”: “desc”, “per_page”: 30 } respuesta = request.get(url, params=params) data = respuesta.json() print(response.status_code) imprimir(datos.claves())
Seré honesto. Este bloque me confundió al principio. La biblioteca de solicitudes era nueva para mí. El diccionario de parámetros con esa sintaxis q parecía extraño. No supe de inmediato qué estaba haciendo .json() o por qué lo necesitaba.
Permítanme desglosarlo simplemente.
request.get() es la forma de llamar a la puerta de GitHub y pedir algo. La URL es la dirección de lo que estás pidiendo. El diccionario de parámetros es la pregunta específica que estás haciendo. En este caso: “dame repositorios de Python, ordenados por estrellas, creados después del 22 de abril, muéstrame 30 resultados”. .json() convierte la respuesta de GitHub de texto sin formato en un diccionario de Python con el que realmente puedes trabajar.
Cuando lo ejecuté, obtuve esto:
200 dict_keys ([‘total_count’, ‘incomplete_results’, ‘items’])
El 200 significa éxito. Esa es la forma en que Internet dice “tu solicitud funcionó”. Si ve 403 o 404, algo salió mal.
El diccionario tiene tres claves. total_count te dice cuántos repositorios coincidieron con la búsqueda. incomplete_results te dice si GitHub tuvo que acortar algo. Y los elementos es donde residen los datos reales.
Luego corrí una segunda cuadra para echar un vistazo al interior:
print(“Total de coincidencias en GitHub:”, datos[‘total_count’]) print(“Repositorios devueltos:”, len(datos[‘items’])) first_repo = datos[‘items’][0]
print(“\nPrimer nombre del repositorio:”, first_repo[‘name’]) print(“Estrellas:”, primer_repo[‘stargazers_count’]) print(“Idioma:”, primer_repo[‘language’]) print(“URL:”, primer_repo[‘html_url’])
Producción:
Total de coincidencias en GitHub: 9228201 Repositorios devueltos: 30 Primer nombre del repositorio: skills Estrellas: 139136 Idioma: Python URL: https://github.com/anthropics/skills
El primer resultado fue un repositorio Anthropic con 139k estrellas. Datos reales. Vivir. Extraído por el código que escribí.
Eso es el extracto hecho.
Paso 2: transformar
Ahora tenía 30 repositorios en una lista de Python, cada uno de los cuales era un diccionario anidado con docenas de campos. La mayoría de los cuales no necesitaba. El paso Transformar es donde se toman esos datos sin procesar y desordenados y se les da forma para convertirlos en algo limpio y útil.
Primero saqué solo los campos que me interesaban y los cargué en un marco de datos de Pandas:
importar pandas como repositorios pd = []
para repositorio en datos[‘items’]: repos.append({ “nombre”: repositorio[‘name’]”propietario”: repositorio[‘owner’][‘login’]”estrellas”: repositorio[‘stargazers_count’]”bifurcaciones”: repositorio[‘forks_count’]”idioma”: repositorio[‘language’]”descripción”: repositorio[‘description’]”url”: repositorio[‘html_url’]”created_at”: repositorio[‘created_at’]
}) df = pd.DataFrame(repositorios) df.head()
Ver aparecer ese marco de datos fue un momento sorprendente. Pasé de una pared de JSON a una tabla limpia y legible con columnas etiquetadas en unas pocas líneas.
Luego hice tres transformaciones:
# Eliminar filas donde falta la descripción df_clean = df.dropna(subset=[‘description’]) # Agregar una bandera viral para repositorios con más de 50 mil estrellas df_clean = df_clean.copy() df_clean[‘viral’] =df_clean[‘stars’].apply(lambda x: ‘Sí’ si x > 50000 else ‘No’) # Ordenar por estrellas descendentes df_clean = df_clean.sort_values(‘estrellas’, ascending=False).reset_index(drop=True) print(“Antes de limpiar:”, len(df)) print(“Después de limpiar:”, len(df_clean))
Producción:
Antes de la limpieza: 30 Después de la limpieza: 29
Un repositorio no tenía descripción y se eliminó. La columna viral apareció limpiamente. Los datos ahora estaban ordenados y estructurados.
Eso es Transformar hecho.
Paso 3: cargar
El último paso. Tome los datos limpios y guárdelos en algún lugar. Mantuve esto simple y lo cargué en un archivo CSV:
df_clean.to_csv(‘github_trending_repos.csv’, index=False) print(“Canalización completa. Archivo guardado.”) print(f”{len(df_clean)} repositorios cargados en github_trending_repos.csv”)
Producción:
Tubería completa. Archivo guardado. 29 repositorios cargados en github_trending_repos.csv
Descargué el archivo y lo abrí. Una hoja de cálculo limpia con 29 filas y 9 columnas. Datos reales de GitHub, moldeados y guardados mediante un proceso que construí desde cero.
Eso es Carga hecha.
Cómo se sintió esto realmente
Antes de esto, cada vez que quería trabajar con datos, buscaba un conjunto de datos públicos que alguien ya había limpiado y subido. Kaggle, búsqueda de conjuntos de datos de Google, donde sea. Siempre fui un consumidor de datos que alguien más había preparado.
Esto cambió algo para mí.
En el momento en que me di cuenta de que podía apuntar Python a una API que me interesaba y extraer datos en vivo yo mismo, las posibilidades parecieron completamente diferentes. No me limito a conjuntos de datos que ya existen. Puedo construir la canalización que crea el conjunto de datos.
Ese es un tipo diferente de poder. Y es una de las cosas que me atrajo hacia la ingeniería de datos en primer lugar.
¿Qué sigue?
Esta tubería es simple por diseño. Estoy al comienzo de mi hoja de ruta y no voy a fingir que estoy usando Airflow o Spark todavía. Pero la base es real. Extraer, transformar, cargar. Funciona. Yo lo construí. Lo entiendo.
El siguiente paso es hacerlo más robusto. Prográmelo para que se ejecute diariamente. Almacene el resultado en una base de datos SQLite en lugar de en un CSV plano. Comience a rastrear la tendencia de los repositorios a lo largo del tiempo.
Y, finalmente, orquesta todo con Airflow. Pero ese es un artículo futuro.
Por ahora, lo más importante que me probé a mí mismo es que construir te enseña cosas que mirar nunca te enseñará. Pasé semanas en tierra de tutoriales y apenas me moví. Pasé una tarde construyendo y entiendo ETL mejor que cualquier video.
Deja de mirar. Empiece a construir.
Esta es la segunda parte de mi serie de ingeniería de datos en curso. Sígueme mientras documento cada paso del viaje, incluidas las partes que no van bien. No dudes en ver mi versión más detallada de ETL en mi canal de YouTube a continuación.
Conéctese conmigo en LinkedIn, YouTube y Twitter.