https://github.com/vinicius999/spotify-api
ETL simples, onde se buscou extrair, processar e carregar dados da API pública do Spotify em um banco de dados Postgresql, usando a linguagem Python.
https://github.com/vinicius999/spotify-api
api bulk-inserts etl postgresql psycopg2 python
Last synced: 11 months ago
JSON representation
ETL simples, onde se buscou extrair, processar e carregar dados da API pública do Spotify em um banco de dados Postgresql, usando a linguagem Python.
- Host: GitHub
- URL: https://github.com/vinicius999/spotify-api
- Owner: Vinicius999
- License: mit
- Created: 2023-03-31T23:52:30.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-06-24T14:32:59.000Z (over 2 years ago)
- Last Synced: 2025-01-12T21:42:33.874Z (about 1 year ago)
- Topics: api, bulk-inserts, etl, postgresql, psycopg2, python
- Language: Python
- Homepage:
- Size: 10.7 MB
- Stars: 0
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
ETL Spotify API
Este repositório contém o 1º desafio da mentoria individual do Programa Desenvolve 2023 - Trilha Dados. O desafio se trata do desenvolvimento de um ETL simples, onde se buscou extrair, processar e carregar dados da API pública do Spotify em um banco de dados PostgreSQL, usando a linguagem Python.
Executar projeto |
Desafio |
Tecnologias |
Dados |
Projeto ETL
## Executar projeto
Para instalar as bibliotecas necessárias para executar este projeto, deve ser usado o arquivo [`requirements.txt`](https://github.com/Vinicius999/Desafio-01-Mentor-Spotify-API/blob/main/requirements.txt). Para fazer isso, abra o terminal, navegue até a pasta do seu priojeto e execute o seguinte comando:
```
pip install -r requirements.txt
```
Feito isso, podemos executar o arquivo [`main.py`](https://github.com/Vinicius999/Desafio-01-Mentor-Spotify-API/blob/main/main.py) usando o comando:
```
python3 main.py
```
## Desafio
1. Utilizar Python para ler dados da [API do Spotify](https://developer.spotify.com/documentation/web-api/tutorials/getting-started) e encontrar episódios onde a palavra "Python" aparecer.
2. Armazenar no banco de dados Postgresql as seguintes informações:
- id do episodio;
- descrição;
- link;
- lista de imagens
3. Baixar as imagens dos eposódios a partir da lista de imagens gravadas no banco de dados e gravar em uma pasta dentro do projeto.
#### Pontos analisados:
- Padronização do código;
- Identação;
- Versionamento;
- Programação Orientada a Objetos
## Tecnologias
## Dados
- Fonte dos dados: [Spotify API](https://developer.spotify.com/)
- Documentação: [documentação](https://developer.spotify.com/documentation/web-api)
## Projeto ETL
### PARTE 1 - Utilizar Python para ler dados da [API do Spotify](https://developer.spotify.com/documentation/web-api/tutorials/getting-started) e encontrar episódios onde a palavra "Python" aparecer.
##### EXTRACT
Para se conectar e ler dados da API do Spotify, foi desenvolvida a classe `Spotipy`, contendo as funções de altenticação e busca de espisódios usando a biblioteca [spotipy](https://spotipy.readthedocs.io/en/2.22.1/):
```python
class Spotipy():
def __init__ (self, CLIENT_ID, CLIENT_SECRET):
self.CLIENT_ID = CLIENT_ID
self.CLIENT_SECRET = CLIENT_SECRET
def authentication(self):
auth_manager = SpotifyClientCredentials(
client_id = self.CLIENT_ID,
client_secret = self.CLIENT_SECRET
)
self.sp = spotipy.Spotify(auth_manager = auth_manager)
return self.sp
def get_all_episodes_with_python(self, sp):
self.episodes = []
self.offset = 0
self.limit = 50 # max limit
self.market='BR'
while True:
self.results = sp.search(q='Python', type='episode', limit=self.limit, offset=self.offset, market=self.market)
self.episodes += self.results['episodes']['items']
self.offset += self.limit
if len(self.results['episodes']['items']) == 0:
break
return self.episodes
```
### PARTE 2 - Armazenar no banco de dados Postgresql as seguintes informações: id do episodio, descrição, link, lista de imagens
##### TRANSFORM
A transformação dos dados foi realizada usando **listas** e **tuplas**, tipos de dados nativos do Python. A motivação do uso desses tipos de dados foi a performance, seja na manipulação ou na inserção desses dados no banco de dados usando **BULK INSERT**.
```python
episode = tuple()
episode_list = list()
for ep in episodes:
episode = ep['id'], ep['description'], ep['external_urls']['spotify'], ep['href']
episode_list.append(episode)
image = tuple()
image_list = list()
for ep in episodes:
for j, im in enumerate(ep['images']):
image = ep['id'], j+1, im['height'], im['width'], im['url']
image_list.append(image)
```
##### LOAD
Para as funções relacionadas ao banco de dados, foi usada a biblioteca [psycopg2](https://pypi.org/project/psycopg2/). Todas essas funções, desde a conexão com o banco, criação das tabelas, inserção e consulta aos dados, estão contidas na classe `Database`:
```python
class Database:
def __init__ (self, HOST, DATABASE, USER, PASSWORD):
print('Connecting to spotifydb...')
self.HOST=HOST
self.DATABASE=DATABASE
self.USER=USER
self.PASSWORD=PASSWORD
def connect_db(self):
self.conn = psycopg2.connect(
host=self.HOST,
database=self.DATABASE,
user=self.USER,
password=self.PASSWORD
)
return self.conn
def create_db(self, sql):
self.conn = self.connect_db()
self.cur = self.conn.cursor()
self.cur.execute(sql)
self.conn.commit()
self.conn.close()
def insert_db(self, sql):
self.conn = self.connect_db()
self.cur = self.conn.cursor()
try:
self.cur.execute(sql)
self.conn.commit()
except (Exception, psycopg2.DatabaseError) as error:
print(f"Error: {error}")
self.conn.rollback()
self.cur.close()
return 1
self.cur.close()
def bulk_insert_db(self, sql, data):
self.conn = self.connect_db()
self.cur = self.conn.cursor()
psycopg2.extras.execute_values(self.cur, sql, data)
self.conn.commit()
self.cur.close()
self.conn.close()
def select_db(self, sql):
self.conn = self.connect_db()
self.cur = self.conn.cursor()
self.cur.execute(sql)
self.recset = self.cur.fetchall()
self.records = []
for rec in self.recset:
self.records.append(rec)
self.conn.close()
return self.records
```
### PARTE 3 - Baixar as imagens dos eposódios a partir da lista de imagens gravadas no banco de dados e gravar em um diretório dentro do projeto
Para o download das imagens, foi usada a biblioteca [requests](https://pypi.org/project/requests/), enquando a biblioteca [os](https://docs.python.org/3/library/os.html) foi usada para criação das pastas e gravação dos arquivos das imagens:
```Python
for i, row in df_images.iterrows():
response = requests.get(row['url'])
image_filename = f"{row['id']}_{i}.jpg"
id = ''
if id != row['id']:
id = row['id']
path = f'images/{id}'
if not os.path.exists(f'{path}/'):
os.mkdir(f'{path}/')
image_path = os.path.join(f'images/{id}', image_filename)
with open(image_path, 'wb') as f:
f.write(response.content)
```