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.
398 lines
20 KiB
Markdown
398 lines
20 KiB
Markdown
# PLANO — Brasiliana Fotográfica → S3
|
||
|
||
> **Comece por aqui.** Documento de transferência: uma sessão nova consegue
|
||
> retomar o trabalho só com este arquivo. Detalhe técnico completo em
|
||
> `README.md`.
|
||
|
||
**Objetivo:** os 13.036 itens da Brasiliana Fotográfica — metadados e imagens
|
||
em qualidade de preservação — depositados em `s3://brasiliana`, organizados
|
||
como acervo arquivístico (procedência + checksums).
|
||
|
||
**Autorização:** a Biblioteca Nacional foi consultada. Confirmou que o material
|
||
é público e que não tem equipe técnica para fornecer um dump; a coleta por
|
||
scraping é o caminho combinado. Ritmo cortês e identificação continuam valendo.
|
||
|
||
> **Reorganização de pastas em 2026-09-10.** Scripts + estado (catálogo,
|
||
> `.sqlite`, `.log`, `.tmp/`, credenciais) mudaram de raiz para `pipeline/`;
|
||
> visualizações foram para `web/`; `exemplo-item/` virou `examples/exemplo-item/`;
|
||
> `censo.py` virou `archive/censo.py`. Todo comando de terminal abaixo já foi
|
||
> atualizado para o novo caminho. Detalhe completo em `README.md` →
|
||
> "Estrutura do repositório".
|
||
>
|
||
> **Mudança de plano em 2026-09-10 (importante, ver 2.6): o achado 2.4 abaixo
|
||
> não se sustentou.** Cloudflare passou a bloquear bitstream via curl também
|
||
> pra itens sem cache de borda — não só HTML. **Tudo (Fases 2 e 3) roda pelo
|
||
> navegador agora, trilha única**, não mais A/B separadas por tipo de nome.
|
||
> A Fase 4 (legado) segue via curl normalmente — domínio diferente
|
||
> (`objdigital.bn.br`), sem esse bloqueio.
|
||
|
||
---
|
||
|
||
## 1. Estado em 2026-09-10
|
||
|
||
| | |
|
||
|---|---|
|
||
| Fase 1 (metadados) | ✅ **completa** — 13.059 registros, 0 erros. 1 falso-positivo conhecido (`.../1`, é a página raiz da comunidade, não um item — excluir na contagem final) |
|
||
| Catálogo | `pipeline/catalogo.jsonl`, re-exportado depois dos reparos (152 itens com `all_preservation_urls`) |
|
||
| Download principal (1 imagem/item) | 🟡 em andamento no navegador |
|
||
| Thumbnails | 🟡 em andamento no navegador |
|
||
| Extras (itens com múltiplos bitstreams, 115 itens) | ✅ completo |
|
||
| Fase 4 (legado objdigital) | 🟡 em andamento, local (`baixador.py --somente-legado`), 2.707 itens com `legacy_url` |
|
||
| `subidor.py` | rodando em `pipeline/`, `--vigiar`, roteia preservacao/thumbnail/legado certo |
|
||
|
||
Não existe mais aba do Brave rodando isso — é uma aba de Chrome comum,
|
||
conectada via extensão Claude-in-Chrome. `coletor.js`/`coletor-resume.js`
|
||
grava em IndexedDB a cada item; fechar a aba não perde nada, mas o *loop*
|
||
para e precisa recolar o script certo pra retomar (ver `tasks/TODO.md`
|
||
pros comandos exatos de cada trilha ativa).
|
||
|
||
---
|
||
|
||
## 2. Cinco achados que não devem ser redescobertos
|
||
|
||
Cada um destes custou horas. Nenhum é óbvio, e vários são contraintuitivos.
|
||
|
||
### 2.1 O sitemap está sete anos desatualizado
|
||
`htmlmap`/`sitemap` são de abril/2019 e listam ~5.300 dos 13.036 itens. Enumerar
|
||
por eles perde **59% do acervo sem erro aparente** — o crawl termina limpo, pela
|
||
metade. Fonte correta: `browse?type=title&rpp=100&offset=N`, percorrido por
|
||
comunidade (o que de quebra etiqueta a instituição de origem).
|
||
|
||
### 2.2 O arquivo de preservação está no DSpace, não no objdigital
|
||
O `DC.identifier` aponta para `objdigital.bn.br` e parece ser o master. É o
|
||
contrário: o bitstream do DSpace tem 5533×4065 (7,4 MB) contra ~2600×2100
|
||
(147 KB) do objdigital. O maior medido: 8679×6484, 34,7 MB — EXIF mostra
|
||
Hasselblad H3D II-39MS a 7216×5412.
|
||
**Inverter isso arquiva o acervo a um quarto da resolução, e nada avisa.**
|
||
|
||
O PDF de 71,9 MB do item 14582 no objdigital não é a mesma imagem melhor: é
|
||
outro objeto, um álbum de várias páginas.
|
||
|
||
### 2.3 O Cloudflare bloqueia automação de navegador — não IP, não geografia
|
||
Medido na mesma máquina, mesmo IP, mesmo instante:
|
||
|
||
| Cliente | Páginas HTML |
|
||
|---|---|
|
||
| Chrome/Brave do usuário | ✅ 200 |
|
||
| `fetch()` de dentro da página | ✅ 200 (>100 seguidas) |
|
||
| Playwright *headed* | ❌ 200 na 1ª, 403 depois |
|
||
| Playwright *headless* | ❌ 403 |
|
||
| curl / httpx | ❌ 403 |
|
||
| Servidor (Hetzner Helsinki) | ❌ 403 |
|
||
|
||
**Proxies não ajudam** — o bloqueio dispara na segunda requisição da mesma
|
||
sessão, não por origem. Testado e descartado. Não repita.
|
||
|
||
### 2.4 Bitstreams passam por curl; páginas HTML não
|
||
`bitstream/...` responde 200 a `curl -L` simples, até com UA de curl. Só o HTML
|
||
é desafiado. É isso que permite baixar os 116 GB fora do navegador, num servidor.
|
||
|
||
### 2.5 Nome de arquivo com percent-encoding leva 403
|
||
Testado com cinco user-agents (Chrome, Safari, Firefox, Googlebot, curl):
|
||
**todos 403** numa URL com `%28`/`%20`, enquanto `curl/8.7.1` puro dá **200**
|
||
numa URL de nome simples. O gatilho é o caminho, não o cliente — variar
|
||
user-agent não resolve. O navegador busca os dois casos sem problema.
|
||
|
||
Daí as duas trilhas — **modelo original, superado, ver 2.6**. Itens da BN
|
||
usam `imagem.jpg` (trilha A); os do IMS usam nomes descritivos com espaços
|
||
e acentos (trilha B).
|
||
|
||
### 2.6 O achado 2.4 não se sustentou — Cloudflare bloqueia bitstream também
|
||
Testado ao vivo em 2026-09-10: item nunca antes acessado, buscado pelo
|
||
navegador (200 OK) e **imediatamente depois** via curl na Finlândia — 403,
|
||
página real do Cloudflare ("Attention Required"). O único item que passava
|
||
por curl (`6066`) só passava porque já tinha sido baixado com sucesso antes
|
||
e ficou em cache de borda (`cf-cache-status: HIT`) — sobra de um caso, não
|
||
regra geral. Pré-aquecer a URL pelo navegador antes de tentar via curl
|
||
**não** transfere o cache pra tornar o curl aceito (testado, falha igual).
|
||
|
||
**Consequência: não existe mais trilha A via servidor.** Tudo — nome simples
|
||
ou com encoding — precisa passar pelo navegador vivo (`fetch()` de dentro da
|
||
página). `baixador.py` na Finlândia fica só pra Fase 4 (objdigital, domínio
|
||
diferente, sem esse bloqueio — ver 2.11).
|
||
|
||
### 2.7 Itens com múltiplos bitstreams reais — não é caso raro
|
||
115 itens (de ~13.058) têm **2 a 6 imagens reais** no bundle ORIGINAL, não
|
||
uma. `citation_pdf_url` não é gerado pra esses (o gerador de citação do
|
||
DSpace não sabe qual é "a" imagem quando há mais de uma) — por isso ficam
|
||
sem `preservation_url` na extração simples. Sintoma: `full_table` tem
|
||
`dc.description` mencionando álbum/página (ex.: "Álbum 0259"), igual ao
|
||
caso do PDF de 71,9 MB do achado 2.2 — mesmo fenômeno, mas dentro do
|
||
próprio DSpace, não só no objdigital.
|
||
|
||
**Como enumerar as imagens reais de um item**, em ordem de confiabilidade:
|
||
1. Contar `.file-wrapper` na página normal do item (não `?show=full`) — bate
|
||
com o número real de bitstreams.
|
||
2. Tentar sequências `/bitstream/{PREFIX}/{h}/{seq}/qualquer-nome.jpg` pra
|
||
`seq` de 1 até N — funciona quando as sequências são contíguas a partir
|
||
de 1 (maioria dos casos).
|
||
3. Quando (2) falha (sequências não contíguas): pegar o nome real do
|
||
arquivo a partir do `<img src>` de cada `.file-wrapper` (é a miniatura,
|
||
nome com `.jpg` duplicado no final — ex. `nome.jpg.jpg`), tirar o último
|
||
`.jpg`, e buscar `/bitstream/handle/{PREFIX}/{h}/{nome-real}` (rota por
|
||
nome exato, não por sequência).
|
||
|
||
`preservation_url` = a maior imagem encontrada (compatibilidade com o
|
||
pipeline); `all_preservation_urls`/`all_preservation_sizes` guardam todas,
|
||
ordenadas da maior pra menor.
|
||
|
||
**Exceção conhecida sem conserto:** handle `20.500.12156.1/7523` — `HTTP
|
||
500` do próprio servidor da BN ao buscar os bitstreams (não é problema de
|
||
nome/padrão). Provável arquivo corrompido do lado deles.
|
||
|
||
### 2.8b Achado 2.8 falha ~62% das vezes em alguns lotes — bitstream de LICENÇA, não thumbnail
|
||
`seq_master+1` às vezes é o bitstream de **LICENÇA** do DSpace (texto puro,
|
||
"LICENÇA DE VEICULAÇÃO E DISTRIBUIÇÃO..."), não a miniatura — visto em
|
||
Marinha e IMS, **2.655 de 4.278 thumbnails** (62%!) baixados errado num
|
||
lote, **146 já tinham subido pro bucket** antes de descobrir (limpo).
|
||
O filtro de tamanho do v1 (`> 2MB → rejeita`) não pega isso: o texto da
|
||
licença é pequeno o bastante (781 bytes) pra passar. **Fix:** validar
|
||
magic bytes (JPEG `FFD8`/PNG) antes de aceitar, tentar seq+2/+3 se falhar,
|
||
e cair pro método do achado 2.7 (`<img src>` da página) como último
|
||
recurso — `baixador-thumb.js` v2. Também blindado no `subidor.py`: rejeita
|
||
qualquer upload cujo conteúdo não comece com magic bytes de imagem,
|
||
independente do nome do arquivo (defesa em camadas).
|
||
|
||
**Lição:** tamanho pequeno não é prova de "é a miniatura" — só magic bytes
|
||
provam que é imagem de verdade.
|
||
|
||
### 2.8 Miniatura gerada pelo DSpace: sequência N+1 (quando contígua)
|
||
Pra item com bitstream original na sequência N, a miniatura que o DSpace
|
||
gera automaticamente costuma ficar na sequência N+1 — confirmado no handle
|
||
`6066`: seq 1 = master (7,7 MB), seq 2 = thumb (56 KB). Mesma rota
|
||
filename-agnostic do achado 2.4 original (o nome na URL não importa, só a
|
||
sequência). Quando as sequências não são contíguas (itens do achado 2.7 via
|
||
método 3), a miniatura de cada imagem é o próprio `<img src>` do
|
||
`.file-wrapper` correspondente — não precisa de request extra.
|
||
|
||
### 2.9 objdigital às vezes tem PDF (álbum), não só JPG — extração pegava o identificador errado
|
||
Alguns itens têm mais de um `DC.identifier` apontando pro objdigital: um
|
||
`.htm` (página de landing) e um `.pdf` (o álbum de verdade, múltiplas
|
||
páginas — mesmo fenômeno do PDF de 71,9 MB do item 14582, achado 2.2). A
|
||
extração original pegava o **primeiro** identificador que batesse com
|
||
"objdigital", que pra 44 itens (a maioria uma sequência do Museu
|
||
Aeroespacial, `14526-14570`, mais o `584`) era o `.htm`, não o `.pdf` —
|
||
perdendo o conteúdo real. De 235 itens com PDF disponível, 191 já estavam
|
||
certos por acaso (o PDF vinha primeiro na lista); só 44 precisaram de
|
||
correção manual (feita em `catalogo.jsonl` e no IndexedDB, antes do
|
||
`baixador.py --somente-legado` alcançar esses handles — nada foi
|
||
contaminado no bucket). **Vale re-checar outros itens com múltiplos
|
||
`DC.identifier` de objdigital por precaução, não só os que têm `.pdf`.**
|
||
|
||
Recheque feito (2026-09-10): mapeamos todos os padrões de extensão em
|
||
2.231 itens com 2+ identifiers objdigital. Achados adicionais:
|
||
- **5 itens** (`1081, 1082, 1084, 4077, 4084`) têm **só HTML**, sem
|
||
`.jpg`/`.pdf` nenhum — são páginas de um visualizador de zoom profundo
|
||
(OpenSeadragon/DZI, pirâmide de blocos, não um arquivo único). **3 já
|
||
tinham sido baixados e subidos como se fossem imagem** (arquivos de
|
||
~2,4 KB, só a página HTML do visualizador) — limpo do bucket, `legacy_url`
|
||
zerado pros 5 (não vale a complexidade de espelhar a pirâmide de tiles
|
||
pra tão poucos itens).
|
||
- **11 itens** têm `.sid` (MrSID, formato comprimido de imagem grande)
|
||
além do `.jpg` — não capturado, ficou como gap conhecido (baixo volume,
|
||
não priorizado).
|
||
|
||
### 2.10 O crawl da Fase 1 não é 100% completo — achado via referência cruzada com o WordPress
|
||
Cruzando os handles citados nos 636 posts do WordPress contra o catálogo,
|
||
2 itens reais (`1799` "Princesa Isabel menina", `4798` "Vista panorâmica de
|
||
Canudos...") existem no site mas não foram enumerados pela Fase 1 — ambos
|
||
sem `citation_pdf_url`, formato de metadado antigo (um é de 2015-04-16,
|
||
uma das primeiras entradas do sistema). Adicionados manualmente ao
|
||
catálogo depois de descobertos.
|
||
|
||
**Isso só foi achado por acaso** (porque um post do blog citava esses
|
||
handles especificamente) — não existe verificação exaustiva de que a
|
||
enumeração por `browse?type=title` capturou 100% dos itens de cada
|
||
comunidade. Pode haver mais itens faltando que nenhum post referencia.
|
||
Não investigado a fundo: seria preciso comparar a contagem de cada
|
||
comunidade contra alguma fonte independente (a BN não expõe OAI-PMH nem
|
||
count via API, até onde sabemos).
|
||
|
||
### 2.11 O objdigital só responde em HTTPS — não era bloqueio
|
||
`legacy_url` na fonte vem como `http://objdigital.bn.br/...`. Conexão HTTP
|
||
simples (porta 80) é resetada (`Recv failure: Connection reset by peer`),
|
||
local e da Finlândia. HTTPS funciona liso com curl puro, local (não
|
||
testado da Finlândia — motivo original de "não alcançável" pode ser outro,
|
||
não investigado). Fix: forçar `https://` no `legacy_url` antes de baixar
|
||
(já aplicado em `baixador.py`).
|
||
|
||
### 2.12 Caractere `#` no nome do arquivo corrompe URL no IndexedDB
|
||
78 itens (mesmo álbum "Album 0035/0259/0260") têm `#` literal no nome real
|
||
do arquivo (ex.: `Alb 0260 199 CT #.jpg`). Algum processo que passou esse
|
||
nome por `new URL(...).pathname` sofreu o efeito clássico: `#` não
|
||
percentado é tratado como início de **fragmento da URL**, e tudo depois
|
||
dele é descartado — a URL salva no IndexedDB virou `.../Alb%20...%20CT%20`
|
||
(sem sequência, sem `#`, sem `.jpg`), 404 garantido. O `catalogo.jsonl`
|
||
local nunca foi tocado por esse bug (tem a URL certa, com `%23`) — fix é
|
||
só reescrever o campo no IndexedDB a partir do catálogo
|
||
(`pipeline/reparo-hash-url.js`).
|
||
|
||
**Lição:** nunca usar `new URL()`/`.pathname` pra manipular nomes de
|
||
arquivo vindos de fonte externa sem antes confirmar que não têm `#`, `?`
|
||
ou outros caracteres especiais de URL não codificados.
|
||
|
||
### 2.13 O mesmo `#` quebra de novo — desta vez no redirect do próprio DSpace
|
||
|
||
Mesmo com a URL do achado 2.12 corrigida no IndexedDB (`%23` correto, forma
|
||
antiga `/bitstream/PREFIX/ID/SEQ/arquivo`), os 78 itens continuavam dando
|
||
404. O DSpace responde a essa forma antiga com um redirect para a forma
|
||
canônica nova (`/bitstream/handle/PREFIX/ID/arquivo`, sem número de
|
||
sequência) — e o `Location` do redirect tem o `#` sem escapar de novo,
|
||
então o `fetch()` do navegador trunca no fragmento ao seguir o redirect
|
||
(`finalUrl` chega faltando `#.jpg`, 404). Fix: pedir direto a forma
|
||
canônica (`/bitstream/handle/...`), pulando o redirect — testado, `200`,
|
||
JPEG válido. `preservation_url` desses 78 itens reescrito no IndexedDB
|
||
para a forma canônica.
|
||
|
||
**Lição:** com `#` no nome do arquivo, não confiar em nenhum redirect do
|
||
servidor — ele pode ter o mesmo bug do lado de lá. Preferir sempre a URL
|
||
final/canônica quando ela for conhecida.
|
||
|
||
### 2.14 Dá pra ler o progresso do BAIXA/BAIXA_THUMB sem o Chrome conectado
|
||
|
||
O progresso das trilhas via navegador (`localStorage.bras_baixados`,
|
||
`bras_thumbs_v2`) sobrevive num arquivo leveldb comum no disco —
|
||
`~/Library/Application Support/Google/Chrome/Default/Local Storage/leveldb`
|
||
— mesmo com a extensão Claude-in-Chrome desconectada (ex.: conflito de conta
|
||
OAuth, sessão anterior perdida). Basta copiar o diretório (evita brigar com
|
||
o `LOCK` que o Chrome mantém aberto) e ler com uma lib leveldb qualquer
|
||
(`classic-level` via npm, sem dependência nativa externa). O valor vem com
|
||
1 byte de prefixo indicando encoding (`0x00`=UTF-16LE, `0x01`=UTF-8/Latin1)
|
||
antes do JSON de verdade. Script pronto: `pipeline/tools/ler-localstorage.js`.
|
||
|
||
**Lição:** perder a conexão com a extensão do navegador não significa perder
|
||
visibilidade do progresso — boa parte do estado do app mora em arquivos
|
||
comuns no disco do usuário, não só "dentro do navegador".
|
||
|
||
---
|
||
|
||
## 3. O acervo
|
||
|
||
DSpace 4.2, handles `20.500.12156.1/*`. **13.058 itens reais** (13.059
|
||
descobertos no crawl, menos 1 falso-positivo — `.../1` é a página raiz da
|
||
comunidade, não um item). Contagem original por comunidade abaixo era de
|
||
13.036; a diferença é ruído de borda (comunidades ganham/perdem item ao
|
||
longo do tempo), não erro de coleta.
|
||
|
||
| Instituição | Itens | | Instituição | Itens |
|
||
|---|--:|---|---|--:|
|
||
| Instituto Moreira Salles | 5.133 | | Fiocruz | 548 |
|
||
| Biblioteca Nacional | 2.726 | | Marinha (DPHDM) | 456 |
|
||
| Museu Aeroespacial | 1.143 | | Arquivo Nacional | 383 |
|
||
| Museu da República | 906 | | Arq. Geral da Cidade do RJ | 248 |
|
||
| Museu Histórico Nacional | 649 | | Leibniz-Institut, Leipzig | 216 |
|
||
| IHGB | 206 | | Fund. Joaquim Nabuco | 190 |
|
||
| Museu Goeldi | 95 | | FGV CPDOC | 79 |
|
||
| IBGE | 58 | | | |
|
||
|
||
**~139,5 GB projetados** (recalculado em 2026-09-10 com médias reais de
|
||
357-474 arquivos já no bucket por categoria, não mais os 6 originais):
|
||
preservação+extras ~136,9 GB (13.152 arquivos, 10,7 MB médio), thumbnails
|
||
~0,9 GB, legado ~1,5 GB (taxa de sucesso ~75%, muito 404 genuíno),
|
||
metadados+WordPress+catálogo <0,2 GB combinados.
|
||
|
||
---
|
||
|
||
## 4. Runbook
|
||
|
||
### Fase 1 — metadados (navegador) ✅ COMPLETA
|
||
Cole `pipeline/coletor-resume.js` (pendentes + erros juntos, numa passada só)
|
||
numa aba em `https://brasilianafotografica.bn.gov.br/brasiliana/`. Acompanhar
|
||
com `await BRAS.status()`. Deixe a aba **ativa na janela dela**: o Chromium
|
||
estrangula `setTimeout` em abas de fundo até 1×/min, e o loop passa a
|
||
rastejar sem erro nenhum. Ao terminar: `await BRAS.exportar()`.
|
||
|
||
### Fases 2 e 3 — trilha única via navegador (não tem mais trilha A/servidor)
|
||
Ver achado 2.6. Na mesma aba (mesmo IndexedDB `bras`), cole em sequência:
|
||
```js
|
||
// pipeline/baixador-navegador.js -- imagem principal, todos os itens
|
||
BAIXA.quantos(); BAIXA.iniciar();
|
||
// pipeline/baixador-thumb.js -- miniaturas
|
||
BAIXA_THUMB.quantos(); BAIXA_THUMB.iniciar();
|
||
// pipeline/baixador-extras.js -- 2a+ imagem dos itens com multiplos bitstreams
|
||
// (rodar reparo-multibitstream.js antes, se ainda nao rodou)
|
||
BAIXA_EXTRA.quantos(); BAIXA_EXTRA.iniciar();
|
||
```
|
||
Em paralelo, em outro terminal:
|
||
```bash
|
||
cd pipeline
|
||
set -a; . .s3env; set +a
|
||
python3 subidor.py --vigiar --catalogo catalogo.jsonl
|
||
```
|
||
Downloads automáticos do Chrome exigem permissão em
|
||
`chrome://settings/content/automaticDownloads` (adicionar
|
||
`https://brasilianafotografica.bn.gov.br`) — sem isso o download "funciona"
|
||
no JS (sem erro) mas nenhum arquivo chega no disco. Vale pro domínio
|
||
inteiro, uma vez só.
|
||
|
||
### Fase 4 — cópias legadas (máquina local)
|
||
```bash
|
||
cd pipeline
|
||
set -a; . .s3env; set +a
|
||
python3 baixador.py --catalogo catalogo.jsonl --somente-legado
|
||
```
|
||
Via curl direto, sem navegador (ver achado 2.11). ~2.707 itens têm
|
||
`legacy_url`, ~328 KB em média.
|
||
|
||
---
|
||
|
||
## 5. Arquivos e credenciais
|
||
|
||
Layout do repo (detalhe em `README.md` → "Estrutura do repositório"):
|
||
scripts + estado ao vivo em `pipeline/`, visualizações em `web/`, item de
|
||
referência em `examples/`, código morto em `archive/`.
|
||
|
||
| Arquivo | O quê |
|
||
|---|---|
|
||
| `tasks/PLANO.md` | Este documento |
|
||
| `README.md` | Referência técnica completa (raiz do projeto) |
|
||
| `pipeline/coletor.js` | Fase 1 — console do navegador, IndexedDB, autoinício |
|
||
| `pipeline/baixador.py` | Fases 2 e 4 — curl → S3, um arquivo por vez |
|
||
| `pipeline/baixador-navegador.js` | Fase 3 — navegador → pasta Downloads |
|
||
| `pipeline/subidor.py` | Fase 3 — Downloads → S3, apaga na hora |
|
||
| `archive/censo.py` | Versão Playwright — **não funciona**, mantida pelo parsing |
|
||
| `pipeline/.s3env.exemplo` | Modelo; chaves reais em `/Users/polux/Projetos/tocador/.env` |
|
||
|
||
**S3:** `hel1.your-objectstorage.com`, bucket `brasiliana` (Hetzner).
|
||
Credenciais em `/Users/polux/Projetos/tocador/.env`
|
||
(`AWS_ACCESS_KEY_ID`, `AWS_SECRET_ACCESS_KEY`). Cópia local em
|
||
`pipeline/.s3env`. Na Finlândia: `/root/.s3env`.
|
||
|
||
**Servidor:** `ssh finland` → 89.167.95.136 (Hetzner Helsinki, root, 31 GB livres).
|
||
|
||
---
|
||
|
||
## 6. Estrutura no bucket
|
||
|
||
```
|
||
s3://brasiliana/
|
||
MANIFEST.md o que é, como foi coletado, quando
|
||
catalogo.jsonl uma linha por item
|
||
itens/20.500.12156.1_6066/
|
||
metadata.json Dublin Core + URL de origem + data UTC
|
||
preservacao/imagem.jpg 5533×4065, 7,4 MB
|
||
legado/icon843660.jpg 147 KB, referência de origem
|
||
manifest-sha256.txt checksum de cada arquivo
|
||
```
|
||
|
||
Não negociável: **SHA-256 de tudo** e **URL de origem + data/hora de captura**.
|
||
Sem os dois é pasta de imagens, não arquivo.
|
||
|
||
---
|
||
|
||
## 7. Pendências
|
||
|
||
1. Terminar a Fase 1 e exportar o catálogo.
|
||
2. Medir a fração da trilha B (`BAIXA.quantos()`) — de graça, sem requisição.
|
||
3. Confirmar a projeção de ~116 GB (hoje: 6 arquivos medidos).
|
||
4. Decidir sobre os PDFs de álbum do objdigital — objetos distintos, o de
|
||
71,9 MB provavelmente não é caso isolado.
|
||
5. Gerar `MANIFEST.md` e `catalogo.jsonl` no bucket ao final.
|
||
|
||
## 8. Direitos
|
||
|
||
Majoritariamente domínio público por antiguidade, mas as 15 instituições têm
|
||
políticas distintas. `dc.rights` e a instituição de origem são preservados
|
||
**por item**: a decisão de redistribuir é item a item, não do acervo em bloco.
|
||
Arquivar para si é uma coisa; republicar é outra.
|