Skip to content

feat(scripts): add merge-pipeline to organize data - #5

Open
gabicastrum wants to merge 1 commit into
othonhugo:mainfrom
gabicastrum:feat/merge-pipeline
Open

feat(scripts): add merge-pipeline to organize data#5
gabicastrum wants to merge 1 commit into
othonhugo:mainfrom
gabicastrum:feat/merge-pipeline

Conversation

@gabicastrum

Copy link
Copy Markdown

Pré-requisitos

  • Ambiente virtual do prawler ativado (.venv)
  • Credenciais do Reddit configuradas
  • Terminal MINGW64 / Git Bash (Windows) ou shell compatível com Bash (pode ser outro, mas foi o terminal testado para esse passo a passo.)

No terminal ou .env passe:

export PRAWLER_CLIENT_ID="${variavel_id_reddit}"
export PRAWLER_CLIENT_SECRET="${variavel_secret_reddit}"

Passo 1 - Buscar posts do subreddit com filtro amplo de IA/chatbots

O filtro é aplicado apenas nos posts (título), ferramentas e termos utilizados por profissionais de TI no dia a dia, como assistentes de código e nomes de modelos/empresas comuns em discussões de dev:

prawler posts brdev \
  --limit 1000 \
  --filter "title ~= \b(?-i:IA)\b|\bChatGPT\b|\bClaude(?:\s*Code)?\b|\bGPT-?\d*\b|\bCopilot\b|\bGemini\b|\bCursor\b|\bintelig[êe]ncia\s+artificial\b" \
  --format jsonl \
  -o posts.jsonl

Notas:

  • (?-i:IA) mantém a sigla IA case-sensitive dentro de uma busca case-insensitive, evitando falso positivo com "ia" minúsculo dentro de outras palavras.
  • Se quiser cobrir também o corpo do post (não só o título), verifique se o -filter é repetível com semântica OR entre campos diferentes (ex: F "title ~= ..." -F "selftext ~= ..."); teste com poucos posts antes de aplicar em massa, pois o comportamento (AND vs OR) não foi confirmado.
  • posts.jsonl guarda os posts completos, na ordem retornada pela API. E essa ordem é preservada até o arquivo final.

Passo 2 - Extrair os IDs dos posts encontrados

python -c "import json; [print(json.loads(l)['id']) for l in open('posts.jsonl', encoding='utf-8')]" > ids.txt

Passo 3(OPCIONAL) - Conferir quantos posts foram encontrados

wc -l ids.txt

Passo 4 - Remover quebras de linha do Windows (CRLF)

⚠️ Obrigatório no Windows/Git Bash. Sem isso, o loop do Passo 5 gera nomes de arquivo inválidos (comments_1v7ber0\r.jsonl).

tr -d '\r' < ids.txt > ids_clean.txt

Passo 5 - Buscar todos os comentários de cada post (sem filtro)

while read -r id; do
    echo "Processando post $id..."
    prawler comments "$id" \
        --limit 1000 \
        --format jsonl \
        -o "comments_${id}.jsonl"
done < ids_clean.txt

Notas:

  • -limit 1000 é alto de propósito, para garantir que a coleta capture o máximo possível de comentários do post, incluindo os de nível 0 que serão filtrados na etapa seguinte. Ajuste conforme o volume médio de comentários dos posts do brdev.
  • Cada arquivo comments_<id>.jsonl contém comentários de todos os níveis (0, 1, 2...) -o filtro por depth == 0 só acontece no Passo 6.
  • Posts sem nenhum comentário geram um arquivo vazio, e não é um erro.

Passo 6 - Consolidar posts + comentários (filtrando depth == 0) em um único arquivo, em ordem

Script que lê os comentários brutos de cada post, mantém apenas os de nível 0 (depth == 0), e intercala cada post com seus comentários filtrados, preservando a ordem de posts.jsonl. O contexto do post (submission_title) já vem embutido em cada comentário retornado pelo prawler, então não é preciso join adicional.

Execute:

python merge_pipeline.py

Notas:.

  • record_type ("post"/"comment") foi adicionado pois facilita filtrar.
  • Os print finais ajudam a validar que o filtro está de fato descartando comentários de níveis mais profundos (comparando total_comentarios_brutos vs total_comentarios_depth0).
  • Nome do arquivo final (dataset_bruto.jsonl) sinaliza que ainda não passou por rotulagem.

Passo 7 - Conferir o resultado final

wc -l dataset_bruto.jsonl

Passo 8 (opcional/dica) - Limpeza dos arquivos intermediários

rm comments_*.jsonl

Mantendo posts.jsonl, ids.txt / ids_clean.txt, merge_pipeline.py e dataset_bruto.jsonl como artefatos finais do pipeline de extração.


Resumo do fluxo

posts.jsonl → ids.txt → ids_clean.txt → comments_<id>.jsonl (N arquivos) → dataset_bruto.jsonl (post + comentários intercalados)
Etapa Comando principal Filtro Saída
1 prawler posts brdev -o posts.jsonl title ~= <termos IA/chatbots> posts.jsonl
2 python -c "..." > ids.txt ids.txt
3 wc -l ids.txt contagem
4 tr -d '\r' < ids.txt > ids_clean.txt ids_clean.txt
5 prawler comments "$id" -o comments_.jsonl nenhum (todos os níveis) comments_.jsonl
6 python merge_pipeline.py depth == 0 (aplicado em Python) dataset_bruto.jsonl
7 wc -l dataset_bruto.jsonl contagem

@othonhugo othonhugo added the enhancement New feature or request label Aug 17, 2026
@othonhugo othonhugo changed the title feat: add merge-pipeline to organize data feat(scripts): add merge-pipeline to organize data Aug 17, 2026
Comment thread merge-pipeline.py
@@ -0,0 +1,39 @@
import json

with open("posts.jsonl", encoding="utf-8") as f:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Seria mais interessante se o caminho de posts.jsonl fosse passado de forma mais dinâmica, talvez por argumentos de linha de comando. Ex:

merge_pipeline.py ./posts.jsonl

Comment thread merge-pipeline.py
resultado.append(comment_record)

with open("dataset_bruto.jsonl", "w", encoding="utf-8") as out:
for item in resultado:

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

O caminho de saída que seria o dataset_bruto.jsonl poderia ser salvo junto ao mesmo diretório do caminho de entrada posts.jsonl (anteriormente), com um prefixo ou sufixo relativo ao nome do arquivo de entrada. Ex:

  • Entrada: ./results/posts.jsonl
  • Saída: ./results/out.posts.jsonl

Comment thread merge-pipeline.py
@@ -0,0 +1,39 @@
import json

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Se puder colocar um comentário no topo do arquivo de explicando o que ele faz e como utilizá-lo.

@othonhugo othonhugo left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Além disso, se puder colocar o script merge-pipeline.py dentro do diretório scripts (ex: `./script/merge_pipeline.py), na raiz do repositório.

Pensei em deixar a branch main focada na biblioteca (e no utilitário) de coleta de dados, e usar a branch workflow para focar nos scripts de automação do pipeline.

@othonhugo othonhugo added the good first issue Good for newcomers label Aug 17, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request good first issue Good for newcomers

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants