Files
brasiliano/pipeline/baixar-faltantes-73.js
rodado 290c4cc21d feat: acervo Brasiliana Fotográfica coletado e mural 3D no ar
Captura integral do acervo da Brasiliana Fotográfica (Biblioteca Nacional)
para s3://brasiliana: 13.060 itens, 12.985 com imagem de preservação, 13.059
com miniatura derivada, 2.137 cópias legadas e 636 posts do blog. 41.444
objetos no ledger.

Os 75 itens sem preservação estão em errors.md: a página do item responde
200, mas a origem serve o bitstream com HTTP 500. Nenhum fica fora do mural,
porque todos têm thumbnail.

Não versionado, por viver no bucket ou ser reconstruível: catálogo,
posts .jsonl, atlas .webp, sqlite de estado e logs. Credenciais ficam de
fora pelo .gitignore.
2026-09-13 20:17:02 +02:00

177 lines
14 KiB
JavaScript

/* ===================================================================
FALTA -- fecha a trilha 1: baixa SO os 73 itens de preservacao que
ainda nao existem nem no bucket nem na fila local de ~/Downloads.
POR QUE ESTE SCRIPT EXISTE (achado 2.16, 2026-09-11)
O contador `bras_baixados` anda pra tras: `marcar()` do
baixador-navegador.js reescreve o array inteiro a partir do FEITOS
carregado quando o script foi colado, entao qualquer aba com snapshot
velho sobrescreve a lista boa por uma mais curta (12.974 -> 12.111 em
meia hora). Recolar o baixador geral re-baixaria ~950+ arquivos que o
contador esqueceu -- ou os 13 mil, se o storage estiver zerado.
Por isso aqui a lista dos faltantes vem EMBUTIDA no script (apurada
por bucket + fila local, nao pelo localStorage) e o progresso vai pra
uma chave propria, `bras_faltantes_73`. Este script NUNCA escreve em
`bras_baixados` -- nao piora a lista que ja esta corrompida.
COMO USAR
1. Cole na aba da Brasiliana (a do coletor, ou qualquer uma da origem).
2. FALTA.iniciar()
3. Os arquivos caem em ~/Downloads com o prefixo BRAS__<handle>__,
que e como o subidor.py (ja rodando, PID 97295) sabe onde guardar.
Nao precisa mexer no subidor: ele vigia a pasta sozinho.
FALTA.status() / FALTA.parar() / FALTA.retomar() / FALTA.pendentes()
FALTA.erros() lista o que falhou, pra uma segunda passada
=================================================================== */
(() => {
/* [handle, preservation_url] -- apurados em 2026-09-11 20:45 UTC */
const FALTANTES = [
["20.500.12156.1/10993", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/10993/1/Alb%200279%20113%20CT.jpg"],
["20.500.12156.1/10995", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/10995/1/Alb%200279%20106%20CT.jpg"],
["20.500.12156.1/6433", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6433/1/0072430cx006-05t.jpg"],
["20.500.12156.1/6520", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6520/1/007_IMG_1008t.jpg"],
["20.500.12156.1/6545", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6545/1/CC-05-01-015-3.jpg"],
["20.500.12156.1/6555", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6555/1/BR_RJANRIO_Q0_ADM_CPA_VFE_FOT_0009_m0003de0003.jpg"],
["20.500.12156.1/6568", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6568/1/BR_RJANRIO_Q0_ADM_CPA_VFE_FOT_0019_m0001de0001.jpg"],
["20.500.12156.1/6570", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6570/1/BR_RJANRIO_Q0_ADM_CPA_VFE_FOT_0024_m0001de0001.jpg"],
["20.500.12156.1/6669", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6669/1/BP-06-TP-01-012.jpg"],
["20.500.12156.1/6670", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6670/1/BP-06-TP-01-015.jpg"],
["20.500.12156.1/6674", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/6674/1/BP-06-TP-01-022.jpg"],
["20.500.12156.1/7034", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7034/1/007A6P3F08-004.jpg"],
["20.500.12156.1/7317", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7317/4/Alb%200294%20069ct.jpg"],
["20.500.12156.1/7326", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7326/4/Alb%200294%20037ct.jpg"],
["20.500.12156.1/7344", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7344/4/Alb%200294%20093ct.jpg"],
["20.500.12156.1/7353", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7353/4/Alb%200294%20097ct.jpg"],
["20.500.12156.1/7355", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7355/4/Alb%200259%20073%20ct.jpg"],
["20.500.12156.1/7358", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7358/1/BR_RJANRIO_OG_0_FOT_0001_021.jpg"],
["20.500.12156.1/7379", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7379/1/BR_RJANRIO_OG_0_FOT_0001_057.jpg"],
["20.500.12156.1/7386", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7386/1/BR_RJANRIO_OG_0_FOT_0001_067.jpg"],
["20.500.12156.1/7393", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7393/1/BR_RJANRIO_OG_0_FOT_0001_089.jpg"],
["20.500.12156.1/7438", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7438/1/BR_RJANRIO_OG_0_FOT_0001_085.jpg"],
["20.500.12156.1/7440", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7440/1/BR_RJANRIO_OG_0_FOT_0001_087.jpg"],
["20.500.12156.1/7457", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7457/4/Alb%200294%20127ct.jpg"],
["20.500.12156.1/7461", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7461/4/Alb%200259%20081ct.jpg"],
["20.500.12156.1/7463", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7463/4/Alb%200294%20106ct.jpg"],
["20.500.12156.1/7475", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7475/4/Alb%200259%20096ct.jpg"],
["20.500.12156.1/7515", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7515/4/Alb%200259%20145ct.jpg"],
["20.500.12156.1/7516", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7516/4/Alb%200259%20139ct.jpg"],
["20.500.12156.1/7517", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7517/3/Album%200035%20297%20CT.jpg"],
["20.500.12156.1/7529", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7529/5/Alb%200259%20130ct.jpg"],
["20.500.12156.1/7743", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7743/1/001ALA011011.jpg"],
["20.500.12156.1/7744", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7744/1/001ALA011012.jpg"],
["20.500.12156.1/7766", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7766/1/001ATK012010.jpg"],
["20.500.12156.1/7802", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7802/1/Alb%200036%20037%20CT%20ok.jpg"],
["20.500.12156.1/7814", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7814/1/Alb%200036%20081%20CT%20ok.jpg"],
["20.500.12156.1/7817", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7817/1/Alb%200036%20087%20CT%20ok.jpg"],
["20.500.12156.1/7848", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7848/1/Alb%200036%20013%20CT%20ok.jpg"],
["20.500.12156.1/7852", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7852/1/Album%200035%20105%20CT.jpg"],
["20.500.12156.1/7861", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7861/1/Album%200035%20088%20CT.jpg"],
["20.500.12156.1/7875", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/7875/1/Album%200035%20078%20CT.jpg"],
["20.500.12156.1/8075", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8075/1/Alb%200038%20009%20CT%20ok.jpg"],
["20.500.12156.1/8128", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8128/1/014AM006009.jpg"],
["20.500.12156.1/8133", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8133/1/014AM010003.jpg"],
["20.500.12156.1/8141", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8141/1/014AM010014.jpg"],
["20.500.12156.1/8145", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8145/1/014AM012006.jpg"],
["20.500.12156.1/8161", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8161/1/014AM012058.jpg"],
["20.500.12156.1/8182", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8182/1/014AM019007.jpg"],
["20.500.12156.1/8187", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8187/1/014AM019013.jpg"],
["20.500.12156.1/8249", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8249/1/014AM002012.jpg"],
["20.500.12156.1/8254", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8254/1/014AM002019.jpg"],
["20.500.12156.1/8262", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8262/1/014AM003015.jpg"],
["20.500.12156.1/8267", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8267/1/014AM004003.jpg"],
["20.500.12156.1/8268", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8268/1/014AM005003.jpg"],
["20.500.12156.1/8271", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8271/1/014AM005005.jpg"],
["20.500.12156.1/8275", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8275/1/014AM005014.jpg"],
["20.500.12156.1/8277", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8277/1/014AM005020.jpg"],
["20.500.12156.1/8286", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8286/1/014AM006002.jpg"],
["20.500.12156.1/8313", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8313/1/001AAN005123.jpg"],
["20.500.12156.1/8316", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8316/1/001ACL019004.jpg"],
["20.500.12156.1/8374", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8374/1/002080NUS0309.jpg"],
["20.500.12156.1/8739", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8739/1/007ALA102.jpg"],
["20.500.12156.1/8761", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8761/1/007ALA015.jpg"],
["20.500.12156.1/8762", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8762/1/007ALA016.jpg"],
["20.500.12156.1/8774", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8774/1/007ALA027.jpg"],
["20.500.12156.1/8781", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8781/1/007ALA033.jpg"],
["20.500.12156.1/8785", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8785/1/007ALA037.jpg"],
["20.500.12156.1/8796", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8796/1/007ALA047.jpg"],
["20.500.12156.1/8804", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8804/1/007ALA054.jpg"],
["20.500.12156.1/8825", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8825/1/007ALA073.jpg"],
["20.500.12156.1/8872", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8872/1/A05F03P02.jpg"],
["20.500.12156.1/8912", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/8912/1/pixinguinha04.jpg"],
["20.500.12156.1/9148", "https://brasilianafotografica.bn.gov.br/brasiliana/bitstream/20.500.12156.1/9148/1/007ALA091.jpg"]
];
const PAUSA = 3000; // mesmo ritmo cortes do baixador geral
const CHAVE = 'bras_faltantes_73'; // chave propria: nao toca em bras_baixados
const sleep = ms => new Promise(r => setTimeout(r, ms));
const jit = () => PAUSA + Math.floor(Math.random() * 1000);
const FEITOS = new Set(JSON.parse(localStorage.getItem(CHAVE) || '[]'));
const marcar = h => { FEITOS.add(h);
localStorage.setItem(CHAVE, JSON.stringify([...FEITOS])); };
const S = {fase: 'ocioso', feito: 0, erros: 0, total: 0, atual: '', parar: false};
const FALHAS = [];
async function baixarUm(handle, url) {
const r = await fetch(url, {credentials: 'same-origin'});
if (!r.ok) throw new Error('HTTP ' + r.status);
const b = await r.blob();
if (b.size < 1024) throw new Error('blob suspeito: ' + b.size + ' bytes');
const orig = decodeURIComponent(url.split('/').pop());
// o prefixo carrega o handle: e assim que o subidor sabe onde guardar
const nome = `BRAS__${handle.replace(/\//g, '_')}__${orig}`.replace(/[\\/:*?"<>|]/g, '_');
const a = document.createElement('a');
a.href = URL.createObjectURL(b); a.download = nome;
document.body.appendChild(a); a.click(); a.remove();
setTimeout(() => URL.revokeObjectURL(a.href), 30000);
return b.size;
}
async function iniciar() {
S.parar = false; S.fase = 'baixando'; FALHAS.length = 0;
const lista = FALTANTES.filter(([h]) => !FEITOS.has(h));
S.total = lista.length; S.feito = 0; S.erros = 0;
console.log(`FALTA: ${lista.length} arquivos (~${Math.ceil(lista.length * PAUSA / 60000)} min)`);
for (let i = 0; i < lista.length; i++) {
if (S.parar) { S.fase = 'parado'; console.log('parado em ' + i); return; }
const [handle, url] = lista[i];
S.atual = `${i + 1}/${lista.length} ${handle}`;
try {
const bytes = await baixarUm(handle, url);
marcar(handle); S.feito++;
console.log(` ok ${handle} ${(bytes / 1048576).toFixed(1)} MB (${i + 1}/${lista.length})`);
} catch (e) {
S.erros++; FALHAS.push({handle, url, erro: e.message});
console.warn(` ERRO ${handle}: ${e.message}`);
if (/HTTP 4|HTTP 5/.test(String(e))) await sleep(60000); // mesmo backoff do geral
}
await sleep(jit());
}
S.fase = 'concluido';
console.log(`\nFALTA concluido. ok=${S.feito} erro=${S.erros}`);
if (FALHAS.length) {
console.log('Rode FALTA.retomar() pra tentar de novo so os que falharam:');
console.table(FALHAS);
} else {
console.log('Trilha 1 fechada: 13.059/13.059. O subidor sobe o resto sozinho.');
}
}
window.FALTA = {
iniciar, status: () => ({...S}), retomar: () => iniciar(),
parar: () => { S.parar = true; },
pendentes: () => FALTANTES.filter(([h]) => !FEITOS.has(h)).map(([h]) => h),
erros: () => [...FALHAS],
limparMarcas: () => localStorage.removeItem(CHAVE),
};
console.log(`FALTA pronto: ${FALTANTES.length} no total, ${window.FALTA.pendentes().length} pendentes.`);
console.log('Rode FALTA.iniciar() para comecar.');
})();