A lightweight, concurrent, and robust batch file downloader for Python. Simplifies fetching multiple files from URLs by using a thread pool, checking for existing files, and reporting failures.
Project description
Grab Harvester
Um downloader de arquivos em lote, leve, concorrente e robusto para Python.
- Grab Harvester
O Problema
Muitas vezes, projetos de software ou análise de dados precisam baixar um grande volume de arquivos de diversas URLs. Realizar essa tarefa de forma manual ou com scripts simples pode ser:
- Lento e Ineficiente: Baixar arquivos um por um (sequencialmente) não aproveita a capacidade da rede e do processador, tornando o processo demorado.
- Frágil: Scripts simples geralmente não lidam bem com falhas de rede, interrupções ou erros de permissão no disco, exigindo intervenção manual para reiniciar.
- Redundante: É comum que o processo reinicie do zero, baixando novamente arquivos que já foram transferidos com sucesso, desperdiçando tempo e banda.
A Solução: Grab Harvester
O Grab Harvester foi criado para resolver exatamente esses problemas, oferecendo uma forma simplificada e poderosa de buscar múltiplos arquivos. Ele automatiza o processo com foco em performance e confiabilidade.
Principais Funcionalidades
- Downloads Concorrentes: Utiliza um pool de threads para baixar vários arquivos simultaneamente, acelerando drasticamente o tempo total da operação.
- Verificação de Integridade: Antes de iniciar um download, o sistema verifica se o arquivo já existe no destino. Se existir, compara o tamanho do arquivo local com o remoto (
Content-Length). O download só é refeito se o arquivo local estiver incompleto, economizando recursos. - Tratamento Robusto de Erros: Captura e encapsula exceções comuns de rede (usando
httpx) e de operações de arquivo (I/O), comoNetworkDownloadErroreFileOperationError. Isso permite que a aplicação que o utiliza possa tratar as falhas de forma granular, sem que o programa inteiro pare inesperadamente. - Simplicidade de Uso: Oferece uma interface limpa e direta para iniciar o processo de download, abstraindo toda a complexidade de gerenciamento de threads e tratamento de erros.
Como Rodar Localmente
Para executar este projeto em sua máquina, você precisará do Python 3.11+ instalado.
1. Clone o repositório
git clone https://github.com/alexcamargos/grab-harvester.git
cd grab-harvester
2. Configuração e Execução
Opção A: Usando uv (Recomendado)
O uv é um gerenciador de pacotes extremamente rápido.
-
Instale as dependências:
uv sync -
Execute o exemplo ou os testes:
uv run examples/library_example.py uv run pytest
Dica: Para atualizar o arquivo
requirements.txt(usado na Opção B) com as versões travadas:uv export --format requirements-txt --output-file requirements.txt
Opção B: Usando pip
-
Crie e ative um ambiente virtual:
python -m venv .venv source .venv/bin/activate # Linux/macOS # .venv\Scripts\activate # Windows
-
Instale as dependências:
pip install -r requirements.txt
-
Execute:
python examples/library_example.py pytest
Como Usar
O Grab Harvester pode ser utilizado tanto para scripts rápidos quanto integrado em sistemas maiores.
Uso Simples (Script Rápido)
A função download é a maneira mais rápida de começar. Ela aceita uma lista de URLs (strings) ou objetos DownloadTask.
from grabharvester import download
urls = [
"https://www.python.org/static/img/python-logo.png",
"https://httpbin.org/image/jpeg"
]
# Baixa os arquivos usando 4 threads simultâneas
download(urls, max_threads=4, destination_dir="./downloads")
Uso Avançado (Integração em Projetos)
Para maior controle e aderência aos princípios SOLID (Injeção de Dependência), utilize as classes DownloadManager e DownloadService.
from pathlib import Path
from grabharvester import DownloadManager, DownloadService, DownloadTask
# 1. Instancie o serviço (pode ser mockado em testes)
service = DownloadService()
# 2. Inicialize o gerenciador
manager = DownloadManager(service, max_threads=2)
# 3. Defina as tarefas
tasks = [
DownloadTask(url='https://www.python.org/static/img/python-logo.png'),
DownloadTask(
url='https://www.google.com/images/branding/googlelogo/1x/googlelogo_color_272x92dp.png',
destination_path=Path('./google_logo.png')
),
]
# 4. Execute
print("Iniciando downloads...")
results = manager.run(tasks)
print(f"Sucessos: {len(results.successes)}")
print(f"Falhas: {len(results.failures)}")
Aprendizados e Arquitetura
O desenvolvimento do Grab Harvester foi uma excelente oportunidade para aplicar e aprofundar conceitos importantes de engenharia de software em Python.
-
Programação Concorrente: A principal melhoria de performance veio do uso de
concurrent.futures.ThreadPoolExecutor. A escolha por threads em vez de processos (ProcessPoolExecutor) foi estratégica, pois a tarefa de download é majoritariamente limitada por I/O (espera de rede), cenário onde threads são mais eficientes e consomem menos memória. -
Design Orientado a Objetos e Inversão de Dependência: A lógica de download foi encapsulada na classe
DownloadService. Isso não apenas organiza o código, mas também facilita os testes. Em vez de chamarhttpx.getdiretamente no código principal, ele é usado dentro de um serviço, o que permite "mockar" a bibliotecahttpxnos testes unitários e simular respostas de rede (sucesso, falha, etc.) sem depender de uma conexão real. -
Exceções Customizadas: Criar exceções específicas como
NetworkDownloadErroreFileOperationErrorem vez de propagar as exceções genéricas (httpx.RequestError,IOError) torna a API doGrab Harvestermais clara e estável. O código que utiliza a biblioteca sabe exatamente que tipo de problemas esperar, sem precisar conhecer os detalhes das dependências internas (comohttpx). -
Testes Unitários Abrangentes com
pytestemocker: A qualidade do projeto é garantida por uma suíte de testes que cobre os principais cenários:- Download bem-sucedido.
- Falhas de rede.
- Erros de escrita em disco.
- Lógica para pular downloads de arquivos já existentes e completos.
- Lógica para refazer downloads de arquivos incompletos.
O uso do
mockerfoi fundamental para isolar oDownloadServicede sistemas externos (rede e sistema de arquivos), garantindo testes rápidos, determinísticos e confiáveis. -
Automação de Qualidade (Pre-commit): Integração de ferramentas de linter e formatadores automáticos via
pre-commit. Isso assegura a criação de código melhor estruturado e formatado, mantendo a base de código limpa e consistente automaticamente.
Autor
Feito com :heart: por Alexsander Lopes Camargos :wave: Entre em contato!
Licença
Este projeto está sob a licença MIT.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file grab_harvester-0.0.2.tar.gz.
File metadata
- Download URL: grab_harvester-0.0.2.tar.gz
- Upload date:
- Size: 14.9 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
2e478b3a7404737d3bf8038a6ba87b957e6c3a3bf2c846aedf7c8999f9f0b720
|
|
| MD5 |
f44456e35b9bc0b236e1413050e53ff9
|
|
| BLAKE2b-256 |
aa7eae7d3c8ed3e8c936a01144021d8c539d386aa54a4f3cc88234fec44978ab
|
File details
Details for the file grab_harvester-0.0.2-py3-none-any.whl.
File metadata
- Download URL: grab_harvester-0.0.2-py3-none-any.whl
- Upload date:
- Size: 11.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.9.18 {"installer":{"name":"uv","version":"0.9.18","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":null,"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
492b5efc3d58f401ff1b1a5995a83018206b9ac591f83e848085e4fd492d29db
|
|
| MD5 |
425f9997a0dc156deb827347115bb0af
|
|
| BLAKE2b-256 |
973f9efa9b0709e525775dc42954f787a37f1fe1ed03838b6b225054b6d276ce
|