Você já estudou Python, conhece os fundamentos, mas agora bate aquela dúvida: "E agora? Como provar que sei programar?"
A resposta é simples: construindo projetos. Não importa se você está buscando seu primeiro emprego ou quer consolidar conhecimento, um portfólio com projetos reais vale mais que 10 certificados.
Neste guia, vou te mostrar 5 projetos Python completos, do mais simples ao intermediário, com código passo a passo. Todos são perfeitos para iniciantes e vão impressionar recrutadores.
Por Que Você Precisa de um Portfólio de Projetos?
Antes de mergulhar nos projetos, entenda: o mercado não contrata quem sabe teoria. Empresas querem ver se você consegue transformar conhecimento em soluções reais.
Um portfólio forte mostra:
- Capacidade de resolver problemas: Você sai do "print('Olá, mundo!')" e cria algo útil
- Domínio de ferramentas: APIs, manipulação de arquivos, automação
- Organização de código: Funções, estrutura limpa, comentários
- Pensamento lógico: Como você estrutura a solução do começo ao fim
Vamos aos projetos!
Projeto 1: Gerador de Senhas Forte e Seguro
O que você vai aprender
- Manipulação de strings
- Biblioteca
random - Validação de entrada do usuário
- Concatenação e formatação
Por que este projeto é importante
Todo mundo precisa de senhas fortes. Este projeto mostra que você entende segurança digital e consegue criar ferramentas úteis.
Código Completo
import random
import string
def gerar_senha(tamanho=12, incluir_especiais=True):
"""
Gera uma senha aleatória forte
Parâmetros:
- tamanho: comprimento da senha (padrão: 12)
- incluir_especiais: se deve incluir caracteres especiais
"""
# Define os caracteres disponíveis
caracteres = string.ascii_letters + string.digits
if incluir_especiais:
caracteres += string.punctuation
# Gera a senha aleatória
senha = ''.join(random.choice(caracteres) for _ in range(tamanho))
return senha
def validar_forca_senha(senha):
"""Valida se a senha é forte"""
tem_maiuscula = any(c.isupper() for c in senha)
tem_minuscula = any(c.islower() for c in senha)
tem_numero = any(c.isdigit() for c in senha)
tem_especial = any(c in string.punctuation for c in senha)
if len(senha) >= 12 and tem_maiuscula and tem_minuscula and tem_numero and tem_especial:
return "🟢 Senha FORTE"
elif len(senha) >= 8:
return "🟡 Senha MÉDIA"
else:
return "🔴 Senha FRACA"
## Menu principal
print("🔐 GERADOR DE SENHAS SEGURAS")
print("-" * 40)
tamanho = int(input("Tamanho da senha (mínimo 8): "))
especiais = input("Incluir caracteres especiais? (s/n): ").lower() == 's'
senha_gerada = gerar_senha(tamanho, especiais)
print(f"\n✅ Senha gerada: {senha_gerada}")
print(f"📊 Força: {validar_forca_senha(senha_gerada)}")
Como melhorar este projeto
- Adicione opção de salvar senhas em arquivo criptografado
- Crie interface gráfica com Tkinter
- Permita gerar múltiplas senhas de uma vez
- Adicione verificação de senhas comprometidas via API
🎲 Projeto 2: Jogo da Adivinhação com Níveis de Dificuldade
O que você vai aprender
- Estruturas condicionais (if/elif/else)
- Loops (while)
- Lógica de programação
- Interação com usuário
Por que este projeto é importante
Jogos ensinam lógica pura. Este projeto demonstra que você domina condicionais, loops e sabe criar experiências interativas.
Código Completo
import random
def jogar_adivinhacao():
print("🎮 JOGO DA ADIVINHAÇÃO")
print("=" * 50)
# Escolhe nível de dificuldade
print("\nEscolha a dificuldade:")
print("1 - Fácil (1-50, 10 tentativas)")
print("2 - Médio (1-100, 7 tentativas)")
print("3 - Difícil (1-500, 5 tentativas)")
nivel = int(input("\nNível: "))
# Define configurações por nível
configuracoes = {
1: {'max': 50, 'tentativas': 10},
2: {'max': 100, 'tentativas': 7},
3: {'max': 500, 'tentativas': 5}
}
config = configuracoes.get(nivel, configuracoes[1])
numero_secreto = random.randint(1, config['max'])
tentativas_restantes = config['tentativas']
print(f"\n🎯 Adivinhe o número entre 1 e {config['max']}")
print(f"⏱️ Você tem {tentativas_restantes} tentativas\n")
# Loop do jogo
while tentativas_restantes > 0:
try:
palpite = int(input(f"Tentativa {config['tentativas'] - tentativas_restantes + 1}: "))
if palpite < 1 or palpite > config['max']:
print(f"❌ Digite um número entre 1 e {config['max']}!")
continue
tentativas_restantes -= 1
if palpite == numero_secreto:
print(f"\n🎉 PARABÉNS! Você acertou em {config['tentativas'] - tentativas_restantes} tentativas!")
return
elif palpite < numero_secreto:
print(f"📈 Muito baixo! Restam {tentativas_restantes} tentativas")
else:
print(f"📉 Muito alto! Restam {tentativas_restantes} tentativas")
except ValueError:
print("❌ Digite apenas números!")
print(f"\n😔 Game Over! O número era {numero_secreto}")
## Executar jogo
jogar_adivinhacao()
## Opção de jogar novamente
while input("\nJogar novamente? (s/n): ").lower() == 's':
jogar_adivinhacao()
Como melhorar este projeto
- Adicione sistema de pontuação baseado em tentativas
- Crie ranking dos melhores jogadores (salvando em arquivo)
- Adicione dicas mais inteligentes (quente/frio)
- Implemente modo multiplayer
Projeto 3: Analisador de Gastos Pessoais
O que você vai aprender
- Manipulação de listas e dicionários
- Leitura e escrita de arquivos CSV
- Cálculos e estatísticas básicas
- Formatação de dados
Por que este projeto é importante
Trabalhar com dados é essencial em qualquer área. Este projeto mostra que você sabe manipular, analisar e apresentar informações de forma organizada.
Código Completo
import csv
from datetime import datetime
from collections import defaultdict
class AnalisadorGastos:
def __init__(self):
self.gastos = []
self.arquivo = 'gastos.csv'
self.carregar_gastos()
def carregar_gastos(self):
"""Carrega gastos do arquivo CSV"""
try:
with open(self.arquivo, 'r', encoding='utf-8') as arquivo:
leitor = csv.DictReader(arquivo)
self.gastos = list(leitor)
# Converte valores para float
for gasto in self.gastos:
gasto['valor'] = float(gasto['valor'])
except FileNotFoundError:
print("📁 Arquivo não encontrado. Criando novo...")
self.criar_arquivo()
def criar_arquivo(self):
"""Cria arquivo CSV se não existir"""
with open(self.arquivo, 'w', newline='', encoding='utf-8') as arquivo:
campos = ['data', 'categoria', 'descricao', 'valor']
escritor = csv.DictWriter(arquivo, fieldnames=campos)
escritor.writeheader()
def adicionar_gasto(self, categoria, descricao, valor):
"""Adiciona novo gasto"""
gasto = {
'data': datetime.now().strftime('%Y-%m-%d'),
'categoria': categoria,
'descricao': descricao,
'valor': float(valor)
}
self.gastos.append(gasto)
# Salva no CSV
with open(self.arquivo, 'a', newline='', encoding='utf-8') as arquivo:
campos = ['data', 'categoria', 'descricao', 'valor']
escritor = csv.DictWriter(arquivo, fieldnames=campos)
escritor.writerow(gasto)
print(f"✅ Gasto de R$ {valor:.2f} adicionado!")
def relatorio_por_categoria(self):
"""Mostra relatório agrupado por categoria"""
if not self.gastos:
print("❌ Nenhum gasto registrado!")
return
categorias = defaultdict(float)
for gasto in self.gastos:
categorias[gasto['categoria']] += gasto['valor']
print("\n📊 RELATÓRIO POR CATEGORIA")
print("-" * 50)
total_geral = sum(categorias.values())
for categoria, valor in sorted(categorias.items(), key=lambda x: x[1], reverse=True):
percentual = (valor / total_geral) * 100
print(f"{categoria:20} R$ {valor:>10.2f} ({percentual:.1f}%)")
print("-" * 50)
print(f"{'TOTAL':20} R$ {total_geral:>10.2f}")
def relatorio_mensal(self):
"""Mostra gastos do mês atual"""
mes_atual = datetime.now().strftime('%Y-%m')
gastos_mes = [g for g in self.gastos if g['data'].startswith(mes_atual)]
if not gastos_mes:
print(f"❌ Nenhum gasto em {mes_atual}")
return
total = sum(g['valor'] for g in gastos_mes)
print(f"\n📅 GASTOS DE {mes_atual}")
print("-" * 70)
print(f"{'Data':<12} {'Categoria':<15} {'Descrição':<25} {'Valor':>10}")
print("-" * 70)
for gasto in sorted(gastos_mes, key=lambda x: x['data']):
print(f"{gasto['data']:<12} {gasto['categoria']:<15} "
f"{gasto['descricao']:<25} R$ {gasto['valor']:>8.2f}")
print("-" * 70)
print(f"{'TOTAL DO MÊS':>52} R$ {total:>8.2f}")
## Menu principal
def menu():
analisador = AnalisadorGastos()
while True:
print("\n💰 ANALISADOR DE GASTOS PESSOAIS")
print("1 - Adicionar gasto")
print("2 - Relatório por categoria")
print("3 - Relatório mensal")
print("4 - Sair")
opcao = input("\nEscolha uma opção: ")
if opcao == '1':
categoria = input("Categoria (ex: Alimentação, Transporte): ")
descricao = input("Descrição: ")
valor = float(input("Valor (R$): "))
analisador.adicionar_gasto(categoria, descricao, valor)
elif opcao == '2':
analisador.relatorio_por_categoria()
elif opcao == '3':
analisador.relatorio_mensal()
elif opcao == '4':
print("👋 Até logo!")
break
if __name__ == "__main__":
menu()
Como melhorar este projeto
- Adicione gráficos com matplotlib
- Crie metas de gastos por categoria
- Implemente filtros por período personalizado
- Adicione exportação para Excel/PDF
Projeto 4: Web Scraper de Notícias
O que você vai aprender
- Biblioteca BeautifulSoup para web scraping
- Requisições HTTP com requests
- Manipulação de HTML
- Tratamento de exceções
Por que este projeto é importante
Web scraping é uma habilidade valiosa no mercado. Este projeto demonstra que você consegue extrair dados da web de forma automatizada.
Código Completo
import requests
from bs4 import BeautifulSoup
from datetime import datetime
import json
class ScraperNoticias:
def __init__(self):
self.headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
}
def buscar_noticias_python(self):
"""Busca notícias sobre Python no site Python.org"""
url = 'https://www.python.org/blogs/'
try:
print("🔍 Buscando notícias sobre Python...")
resposta = requests.get(url, headers=self.headers, timeout=10)
resposta.raise_for_status()
soup = BeautifulSoup(resposta.content, 'html.parser')
# Encontra artigos (ajuste o seletor conforme o site)
artigos = soup.find_all('article', class_='blog-widget', limit=5)
noticias = []
for artigo in artigos:
try:
titulo_tag = artigo.find('h2', class_='widget-title')
titulo = titulo_tag.get_text(strip=True) if titulo_tag else 'Sem título'
link_tag = titulo_tag.find('a') if titulo_tag else None
link = link_tag['href'] if link_tag else '#'
# Monta link completo
if link.startswith('/'):
link = f'https://www.python.org{link}'
resumo_tag = artigo.find('p')
resumo = resumo_tag.get_text(strip=True)[:200] if resumo_tag else 'Sem descrição'
noticia = {
'titulo': titulo,
'link': link,
'resumo': resumo,
'data_coleta': datetime.now().strftime('%Y-%m-%d %H:%M')
}
noticias.append(noticia)
except Exception as e:
print(f"❌ Erro ao processar artigo: {e}")
continue
return noticias
except requests.exceptions.RequestException as e:
print(f"❌ Erro ao acessar o site: {e}")
return []
def exibir_noticias(self, noticias):
"""Exibe as notícias formatadas"""
if not noticias:
print("❌ Nenhuma notícia encontrada!")
return
print(f"\n📰 {len(noticias)} NOTÍCIAS ENCONTRADAS")
print("=" * 80)
for i, noticia in enumerate(noticias, 1):
print(f"\n{i}. {noticia['titulo']}")
print(f" {noticia['resumo']}...")
print(f" 🔗 {noticia['link']}")
print(f" 📅 Coletado em: {noticia['data_coleta']}")
print("-" * 80)
def salvar_json(self, noticias, arquivo='noticias.json'):
"""Salva notícias em arquivo JSON"""
try:
with open(arquivo, 'w', encoding='utf-8') as f:
json.dump(noticias, f, ensure_ascii=False, indent=4)
print(f"✅ Notícias salvas em {arquivo}")
except Exception as e:
print(f"❌ Erro ao salvar arquivo: {e}")
## Executar scraper
def main():
scraper = ScraperNoticias()
print("🌐 WEB SCRAPER DE NOTÍCIAS PYTHON")
print("=" * 80)
noticias = scraper.buscar_noticias_python()
scraper.exibir_noticias(noticias)
if noticias:
salvar = input("\n💾 Deseja salvar em JSON? (s/n): ")
if salvar.lower() == 's':
scraper.salvar_json(noticias)
if __name__ == "__main__":
# Primeiro, instale as bibliotecas:
# pip install requests beautifulsoup4
main()
Como melhorar este projeto
- Adicione scraping de múltiplos sites
- Implemente agendamento automático (cron/schedule)
- Crie sistema de notificações por email
- Adicione análise de sentimento nas notícias
Projeto 5: Automatizador de Tarefas Diárias
O que você vai aprender
- Automação de arquivos e pastas
- Biblioteca os e shutil
- Agendamento de tarefas
- Organização de código em módulos
Por que este projeto é importante
Automação economiza tempo e mostra que você resolve problemas reais. Este projeto impressiona porque tem aplicação prática imediata.
Código Completo
import os
import shutil
from datetime import datetime
from pathlib import Path
class AutomatizadorArquivos:
def __init__(self, pasta_origem):
self.pasta_origem = Path(pasta_origem)
self.extensoes = {
'Imagens': ['.jpg', '.jpeg', '.png', '.gif', '.bmp', '.svg'],
'Documentos': ['.pdf', '.doc', '.docx', '.txt', '.xlsx', '.pptx'],
'Videos': ['.mp4', '.avi', '.mkv', '.mov', '.flv'],
'Musicas': ['.mp3', '.wav', '.flac', '.aac'],
'Compactados': ['.zip', '.rar', '.7z', '.tar', '.gz'],
'Codigo': ['.py', '.js', '.html', '.css', '.java', '.cpp']
}
def organizar_downloads(self):
"""Organiza arquivos por tipo em pastas"""
if not self.pasta_origem.exists():
print(f"❌ Pasta {self.pasta_origem} não existe!")
return
print(f"🗂️ Organizando arquivos em {self.pasta_origem}")
arquivos_movidos = 0
for arquivo in self.pasta_origem.iterdir():
if arquivo.is_file():
extensao = arquivo.suffix.lower()
# Determina categoria do arquivo
categoria = self.obter_categoria(extensao)
if categoria:
# Cria pasta da categoria se não existir
pasta_destino = self.pasta_origem / categoria
pasta_destino.mkdir(exist_ok=True)
# Move arquivo
try:
destino = pasta_destino / arquivo.name
# Se arquivo já existe, adiciona timestamp
if destino.exists():
nome_base = arquivo.stem
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
destino = pasta_destino / f"{nome_base}_{timestamp}{extensao}"
shutil.move(str(arquivo), str(destino))
arquivos_movidos += 1
print(f"✅ {arquivo.name} → {categoria}/")
except Exception as e:
print(f"❌ Erro ao mover {arquivo.name}: {e}")
print(f"\n🎉 {arquivos_movidos} arquivos organizados!")
def obter_categoria(self, extensao):
"""Retorna categoria baseada na extensão"""
for categoria, extensoes in self.extensoes.items():
if extensao in extensoes:
return categoria
return None
def limpar_arquivos_antigos(self, dias=30):
"""Remove arquivos mais antigos que X dias"""
agora = datetime.now().timestamp()
limite = dias * 24 * 60 * 60 # Converte dias para segundos
removidos = 0
for arquivo in self.pasta_origem.rglob('*'):
if arquivo.is_file():
idade = agora - arquivo.stat().st_mtime
if idade > limite:
try:
arquivo.unlink()
print(f"🗑️ Removido: {arquivo.name}")
removidos += 1
except Exception as e:
print(f"❌ Erro ao remover {arquivo.name}: {e}")
print(f"\n🎉 {removidos} arquivos antigos removidos!")
def gerar_relatorio(self):
"""Gera relatório de arquivos por categoria"""
print("\n📊 RELATÓRIO DE ARQUIVOS")
print("=" * 60)
categorias_count = {}
total_tamanho = 0
for arquivo in self.pasta_origem.rglob('*'):
if arquivo.is_file():
extensao = arquivo.suffix.lower()
categoria = self.obter_categoria(extensao) or 'Outros'
tamanho = arquivo.stat().st_size
if categoria not in categorias_count:
categorias_count[categoria] = {'count': 0, 'size': 0}
categorias_count[categoria]['count'] += 1
categorias_count[categoria]['size'] += tamanho
total_tamanho += tamanho
for categoria, dados in sorted(categorias_count.items()):
tamanho_mb = dados['size'] / (1024 * 1024)
print(f"{categoria:15} {dados['count']:>5} arquivos {tamanho_mb:>10.2f} MB")
print("=" * 60)
print(f"{'TOTAL':15} {sum(d['count'] for d in categorias_count.values()):>5} arquivos "
f"{total_tamanho / (1024 * 1024):>10.2f} MB")
## Menu principal
def menu():
pasta = input("📁 Digite o caminho da pasta (ou Enter para Downloads): ").strip()
if not pasta:
# Pasta padrão de Downloads
pasta = str(Path.home() / "Downloads")
automatizador = AutomatizadorArquivos(pasta)
while True:
print(f"\n🤖 AUTOMATIZADOR DE ARQUIVOS")
print(f"📂 Pasta: {pasta}")
print("\n1 - Organizar arquivos por tipo")
print("2 - Gerar relatório")
print("3 - Limpar arquivos antigos (30+ dias)")
print("4 - Sair")
opcao = input("\nEscolha: ")
if opcao == '1':
automatizador.organizar_downloads()
elif opcao == '2':
automatizador.gerar_relatorio()
elif opcao == '3':
confirma = input("⚠️ Remover arquivos com 30+ dias? (s/n): ")
if confirma.lower() == 's':
automatizador.limpar_arquivos_antigos(30)
elif opcao == '4':
print("👋 Até logo!")
break
if __name__ == "__main__":
menu()
Como melhorar este projeto
- Adicione agendamento automático (executar todo dia às 8h)
- Crie regras personalizadas de organização
- Implemente backup automático na nuvem
- Adicione interface gráfica com PyQt ou Tkinter
Como Publicar Seus Projetos no GitHub
Ter os projetos prontos é só metade do caminho. Você precisa mostrá-los ao mundo. Veja o passo a passo:
1. Crie uma conta no GitHub
Acesse github.com e crie sua conta gratuita.
2. Crie um repositório para cada projeto
- Clique em "New Repository"
- Nome: "gerador-senhas-python" (use nomes descritivos)
- Adicione descrição clara do que o projeto faz
- Marque "Add a README file"
3. Escreva um README.md profissional
## 🔐 Gerador de Senhas Seguras
Ferramenta Python para criar senhas fortes e validar sua segurança.
## 🚀 Funcionalidades
- Gera senhas aleatórias personalizáveis
- Valida força da senha (fraca/média/forte)
- Permite escolher tamanho e caracteres especiais
## 📦 Como usar
```bash
python gerador_senhas.py
🛠️ Tecnologias
- Python 3.x
- Bibliotecas: random, string
📸 Screenshot
[Adicione uma imagem do seu projeto rodando]
<h3>4. Faça commits organizados</h3>
```python
## No terminal/cmd:
git init
git add .
git commit -m "Adiciona gerador de senhas com validação"
git branch -M main
git remote add origin https://github.com/seu-usuario/gerador-senhas-python.git
git push -u origin main
Como Usar Estes Projetos em Entrevistas
Quando um recrutador perguntar "Quais projetos você já fez?", você pode responder:
"Desenvolvi 5 projetos Python que demonstram diferentes habilidades:
- Gerador de Senhas: Mostra domínio de strings, random e validação de dados
- Jogo de Adivinhação: Demonstra lógica com loops e condicionais
- Analisador de Gastos: Trabalha com CSV, manipulação de dados e relatórios
- Web Scraper: Extrai dados automaticamente de sites usando BeautifulSoup
- Automatizador: Organiza arquivos e elimina tarefas repetitivas
Todos estão no meu GitHub com código documentado e README profissional."
Próximos Passos
Agora que você tem 5 projetos no portfólio, é hora de:
- Adicionar testes: Aprenda pytest e adicione testes aos projetos
- Melhorar o código: Refatore seguindo PEP 8 e boas práticas
- Adicionar complexidade: Implemente as melhorias sugeridas em cada projeto
- Criar projetos maiores: API REST, dashboard com dados reais, bot de Telegram
- Contribuir em open source: Procure projetos Python no GitHub e contribua
Conclusão
Você não precisa de 50 projetos para conseguir seu primeiro emprego. Você precisa de 5 projetos bem feitos que demonstrem:
- Capacidade de resolver problemas reais
- Código limpo e organizado
- Documentação clara
- Variedade de habilidades
Pegue estes 5 projetos, publique no GitHub, melhore-os continuamente e use em entrevistas. Isso vai te destacar de 90% dos candidatos que só têm certificados.
Se quiser uma formação estruturada para acelerar, veja nosso ranking dos melhores cursos de Python e escolha a opção certa para o seu perfil.
Agora é com você. Escolha o primeiro projeto, abra seu editor de código e comece a construir seu portfólio hoje!
Boa sorte, futuro programador Python!