Passo 1 · Módulo 1 · Extrair · Módulo 1 · Extrair · Extrair um guia que o scrape não vê
Do guia da Rocketseat ao Warp · Visual Course

Extrair um guia que o scrape não vê

O guia da Rocketseat vive num Notion que devolve 6 bytes para um scraper comum. Você vai entender por quê, e sair com a extração completa e fiel — emojis e typo incluídos.

Leia primeiro (fonte primária)
Rocketseat — "O guia de terminal da Rocketseat" (Notion)

A página-fonte deste curso inteiro. Esta lição destila como tirar 100% do conteúdo dela sem inventar nada — o insumo de tudo que vem depois.

Leia a versão simples, ou abra a camada técnica em qualquer seção.
1

A grande ideia


Uma página do Notion parece um site normal, mas o texto não vem no HTML: vem depois, montado por JavaScript no navegador. Quem baixa o HTML cru recebe uma casca vazia.

Pense como… pedir a planta de um apartamento decorado e receber só a planta baixa: as paredes estão lá, os móveis não. A analogia quebra num ponto — no Notion nem as paredes vêm, vem só a placa com o nome do prédio.

A página é uma SPA: o HTML inicial carrega um bundle que faz POST /api/v3/loadPageChunk e só então injeta os blocos no DOM. Um fetcher HTTP simples nunca executa esse JavaScript, então o que ele devolve é o <title> e pouco mais. A saída literal do brightdata scrape -f markdown nesta página foram 6 bytes: a string Notion.

O QUE MUDA ENTRE AS DUAS CHAMADAS brightdata scrape -f markdown $ brightdata scrape "$URL" -f markdown $ wc -c guia-raw.md 6 guia-raw.md $ cat guia-raw.md Notion brightdata browser (renderiza o JS) $ brightdata browser --session rs \ open "$URL" $ brightdata browser --session rs \ get text -o page-text.txt 3544 bytes, 55 linhas
O mesmo URL, duas ferramentas: uma lê bytes, a outra roda o navegador. A diferença é 6 bytes contra 3.544.
ANATOMIA DE UMA PÁGINA CLIENT-RENDERED HTML inicial — casca + <script> ~40 KB, sem texto bundle JS — o app do Notion app-*.js POST /api/v3/loadPageChunk os blocos, em JSON DOM montado — o texto que você lê notion-*-block
As quatro camadas de uma página do Notion. Um fetcher HTTP para na primeira; o texto nasce na quarta.
Antes de rolar: o scrape devolveu 6 bytes. Quantos links externos o guia tem escondidos nesse HTML que só o navegador monta?
9. iTerm2, JetBrainsMono, iTerm2colorschemes, Fish Shell, Starship, bat, zoxide, eza e fzf. Todos foram extraídos casando cada <a href> com o texto da âncora — não adivinhando pela lista de plugins.
2

Escolher a ferramenta certa


Não existe uma ferramenta melhor: existe a barata que às vezes basta, e a cara que sempre funciona. A regra é começar pela barata e escalar quando a saída vier vazia.

O HTML cru já contém o texto? sim brightdata scrape 1 requisição, barato não brightdata browser sessão real, renderiza JS Regra: tente scrape primeiro; se vier vazio ou minúsculo, escale para browser.
A árvore de decisão que economiza tempo e dinheiro em qualquer extração.
scrape Uma requisição HTTP, sem navegador Rápido e barato por página Ótimo para blog, docs, HTML estático Devolve casca em SPA (Notion, React) Sem clique, scroll ou espera browser Navegador real, geo-direcionado Executa o JavaScript da página get text / get html / screenshot Sessão nomeada, sobrevive entre comandos Aceita scroll e espera por lazy-load veredito: SPA ⇒ browser, sempre
As duas subcomandos do mesmo CLI. A escolha é sobre onde o conteúdo mora, não sobre qualidade.

A sessão nomeada rs mantém o navegador vivo entre os comandos — abrir, ler o texto, ler o HTML, fechar.

terminal · extração completa em 4 comandos
brightdata browser --session rs open "$URL" --timeout 90000
brightdata browser --session rs get text -o page-text.txt
brightdata browser --session rs get html -o page.html
brightdata browser --session rs close

Como chegar: brightdata browser --help lista todos os subcomandos: snapshot, screenshot, scroll, network, cookies.

O QUE CADA EXTRATOR PRESERVA get text prosa ✓ href ✗ emoji ✗ get html prosa ✓ href ✓ alt=emoji ✓ usado do texto do html do html
O que cada saída preserva. A extração fiel usa as duas: prosa do texto, links e emojis do HTML.

O get text devolve prosa limpa mas descarta atributos: os href somem e os emojis (que o Notion renderiza como <img alt="💜"> sobre um spritesheet) viram nada. O get html guarda os dois. Foi casando os dois que a extração ficou fiel: a prosa saiu do texto, os 9 links e os 4 emojis saíram do HTML.

3

Em uma imagem


POR QUE UMA FALHA E A OUTRA NÃO CLI scrape browser open get text/html Rede GET html GET + JS bundle loadPageChunk Resultado 6 bytes 3.544 bytes
As mesmas três camadas nas duas tentativas. O que muda é a rede: sem executar o bundle, a chamada de dados nunca acontece.
BYTES RECUPERADOS scrape -f markdown 6 B browser get text 3544 B browser get html 117827 B
Bytes de saída por método, na mesma URL. A escala fala sozinha.
O QUE A PÁGINA TEM 55 linhas de conteúdo 9 links externos 4 emojis recuperados 1 bloco não extraível
O inventário completo da página, item por item. O último número é o que uma extração honesta declara em vez de esconder.
A SESSÃO DE EXTRAÇÃO, PASSO A PASSO scrape 6 bytes 1 browser open sessão rs 2 get text 3.5 KB 3 get html 118 KB 4 scroll ×8 lazy-load 5 network vídeo? 6 close libera 7
A sessão inteira, em ordem. Os passos 5 e 6 foram a tentativa (falhada) de acordar o bloco de vídeo.
terminal — a tentativa que falhou $ brightdata scrape "$URL" -f markdown -o guia-raw.md Scraping https://efficient-sloth-d85.notion.site/... Output written to guia-raw.md $ wc -c guia-raw.md 6 guia-raw.md $ cat guia-raw.md Notion
A sessão real que provou o problema. Seis bytes: o título da aba, nada do guia.
4

Fidelidade: o que quase se perde


Extrair não é só pegar o texto: é pegar o texto exatamente como está. Três coisas escapam por padrão — e as três estavam neste guia.

1 · Os emojis somem

O get text devolveu "Feito com pela Rocketseat." — com dois espaços e nada no meio. O Notion desenha emoji como <img alt="💜"> com um spritesheet no background; o extrator de texto joga fora a imagem.

Correção: varrer o HTML por alt="…" e reinserir. Recuperados: 🎨 no título, 💜 no crédito, 🔥 no vídeo, 💜 no rodapé.

2 · O typo do original

A página diz "Bora descobri na prática" — sem o r. A primeira versão do arquivo extraído "consertou" para descobrir.

Isso é um bug de extração, não uma melhoria: uma extração fiel reproduz o original, inclusive o que parece errado. Revertido para o texto verbatim.

3 · O que não dá para extrair

O bloco de vídeo é um notion-video-block com arquivo hospedado no próprio Notion — não é YouTube. A URL assinada só carrega sob interação do player; após rolar a página inteira, o bloco seguiu em Carregando… e nenhuma URL de mídia apareceu no browser network.

A resposta honesta é registrar o buraco, com o motivo, no próprio artefato — nunca inventar uma transcrição.

1 / 3

Troca cada <img alt="…"> pelo emoji e mostra o contexto ao redor, para saber onde reinserir.

recuperando os emojis do HTML
python3 - <<'PY'
import re
h = open('raw-page.html', encoding='utf-8').read()
plain = re.sub(r'<img[^>]*alt="([^"]{1,12})"[^>]*>', r'{\1}', h)
plain = re.sub(r'<[^>]+>', '', plain)
for m in re.finditer(r'\{([^}]{1,12})\}', plain):
    print(repr(m.group(1)), '::', plain[m.start()-70:m.end()+70])
PY

Como chegar: Rode dentro da pasta extract/ do projeto, onde ficam raw-page.html e raw-page-text.txt.

OS ARTEFATOS DA EXTRAÇÃO extract/ [intacto] └─ guia-rocketseat.md o artefato final, fiel [novo] └─ raw-page-text.txt get text — 55 linhas [novo] └─ raw-page.html get html — links e emojis [novo]
Os três arquivos da extração. Guardar os brutos é o que permite refazer o diff meses depois e provar que nada mudou.
extração descuidada Emojis somem sem ninguém notar Typos "corrigidos" em silêncio Links reconstruídos de memória Buracos preenchidos por invenção Impossível auditar depois extração fiel Emojis recuperados do alt do HTML Texto verbatim, typo incluído Links casados com a âncora real Buraco declarado, com o motivo Brutos guardados para o diff fidelidade é auditabilidade
As duas terminam com um arquivo. Só uma delas você pode defender.
EXTRAÇÃO
Por que o scrape devolveu 6 bytes?
clique para virar
A página é client-rendered: o HTML inicial só carrega o bundle JS. Sem executar o bundle, o texto nunca é injetado no DOM.
FIDELIDADE
O original tem um typo. O que fazer?
clique para virar
Manter verbatim. Extração fiel reproduz o original — corrigir é introduzir uma diferença que ninguém pediu.
HONESTIDADE
E o que não dá para extrair?
clique para virar
Registrar o buraco com o motivo, dentro do próprio artefato. Nunca preencher com invenção.
5

Experimente


A prova de que a extração está completa não é "eu li e parece completo": é um diff programático entre o texto bruto da página e o markdown final.

Como a extração foi provada
1
Normalizar os dois lados: tirar decoração markdown (**, `, [texto](url)texto), colapsar espaços, remover emojis dos dois lados e aplicar NFKC.
2
Listar as 55 linhas de conteúdo do raw-page-text.txt e ignorar as 3 de chrome do Notion (Ir al contenido, Comienza ahora, Cargando…).
3
Para cada linha, checar se ela aparece no markdown normalizado.
4
Contar as ausentes. O alvo é zero.
Agora você: rode o mesmo diff depois de editar o arquivo extraído — qualquer parágrafo que você reescrever aparece como ausente na hora.
COMO A EXTRAÇÃO FOI PROVADA Normalizar markdown → prosa Filtrar chrome do Notion Diferenciar linha a linha Contar ausentes = 0 tira ** ` []() 3 linhas 55 linhas critério D1
O pipeline da prova. Sem a normalização, a decoração do markdown gera 22 falsos ausentes.
terminal — a prova da extração $ python3 diff-extracao.py linhas de conteudo: 55 | chrome do Notion: 3 | AUSENTES: 0 D1: PASS
O resultado real. Zero linhas ausentes é o critério do D1 no SCOPE.md.
Revisão da lição 1
O brightdata scrape devolveu quase nada numa página. Qual é o próximo passo?
a está certa: o browser roda um navegador real e executa o JS que monta o DOM. b falha porque o problema não é bloqueio geográfico — é renderização no cliente; trocar de país devolve os mesmos 6 bytes. c parece esperto, mas o bundle não carrega os dados: ele os busca depois, numa chamada que só acontece dentro do navegador.
A página tem um typo evidente. A extração deve:
b está certa: o artefato precisa ser fiel à fonte; anotar é opcional, alterar não. a introduz uma divergência silenciosa entre artefato e original. c é melhor que a por ser rastreável, mas ainda entrega um texto que a fonte não tem.
Quer ver a extração de outra página que resiste? Me peça — o mesmo par scrapebrowser resolve quase tudo. Na próxima lição a gente traduz cada instrução do guia, escrita para iTerm2, na chave equivalente do Warp.