Extrair Planejamento de Aula para SQLite
O extrair_planejamento.py lê arquivos HTML de Planejamento de Aula
(exportados do sistema acadêmico da UTFPR) e grava as informações em três
bancos SQLite3 distintos, um para cada tipo de conteúdo:
| Banco | Tabela | Conteúdo |
|---|---|---|
sincrona.db | atividades_sincronas | Atividades Síncrona (aulas presenciais/síncronas) |
assincrona.db | atividades_assincronas | Atividades Assíncrona (EaD) |
procedimentos.db | procedimentos_ensino | Procedimentos de Ensino |
Cada registro guarda também a origem (nome do arquivo, disciplina, código e professor), o que permite consolidar várias disciplinas nos mesmos bancos.
Pré-requisitos
- Python 3.9 ou superior (o script usa
argparse.BooleanOptionalAction). - Biblioteca beautifulsoup4.
- Linux / macOS
- Windows
python3 -m pip install beautifulsoup4
pip install beautifulsoup4
py -m pip install beautifulsoup4
Uso rápido
# Processa arquivos específicos (bancos no diretório atual)
python3 extrair_planejamento.py aula1.html aula2.html
# Processa todos os .html de uma pasta -> bancos em ./htmls/bancos
python3 extrair_planejamento.py --dir ./htmls
# Define explicitamente a pasta de saída
python3 extrair_planejamento.py --dir ./htmls --out ./bancos
Se você executar python3 extrair_planejamento.py sem nenhum parâmetro, o
script procura por *.html no diretório atual e grava os bancos ali mesmo.
Opções da linha de comando
| Opção | Descrição |
|---|---|
arquivos | Um ou mais arquivos HTML de entrada (posicional). |
--dir DIR | Processa todos os *.html do diretório informado. |
--out OUT | Diretório de saída dos bancos. Ver regra de destino abaixo. |
--limpar / --no-limpar | Esvazia (ou não) as tabelas antes de inserir. Padrão: --limpar. |
-h, --help | Mostra a ajuda. |
Você pode combinar arquivos posicionais com --dir; o script junta as duas
listas e remove duplicatas.
Onde os bancos são gravados
O destino é resolvido nesta ordem:
--outinformado → usa exatamente o diretório indicado.--outomitido +--dir X→ grava emX/bancos(ex.:--dir ./htmls→./htmls/bancos).--outomitido e sem--dir→ grava no diretório atual.
Limpeza das tabelas (--limpar)
Por padrão, o script esvazia as três tabelas e reinicia os IDs antes de inserir. Isso torna a execução idempotente: rodar duas vezes sobre os mesmos arquivos mantém a contagem estável, sem duplicar registros.
# Padrão: zera as tabelas e regrava (evita duplicação)
python3 extrair_planejamento.py --dir ./htmls
# Acrescenta aos dados já existentes (não apaga nada)
python3 extrair_planejamento.py --dir ./htmls --no-limpar
--limpar apaga todos os registros dos bancos de destino, inclusive de
disciplinas importadas em execuções anteriores cujos HTMLs não estejam na pasta
atual. Se o seu objetivo é montar um banco consolidado ao longo de várias
execuções, use --no-limpar a partir da segunda importação.
Esquema dos bancos
- sincrona.db
- assincrona.db
- procedimentos.db
Tabela atividades_sincronas:
| Coluna | Tipo | Descrição |
|---|---|---|
id | INTEGER | Chave primária (autoincremento). |
arquivo | TEXT | Nome do HTML de origem. |
disciplina | TEXT | Nome da disciplina. |
codigo | TEXT | Código da disciplina/turma. |
professor_disciplina | TEXT | Professor(a) da disciplina. |
semana | INTEGER | Número da semana. |
semana_inicio | TEXT | Data inicial da semana (dd/mm/aaaa). |
semana_fim | TEXT | Data final da semana (dd/mm/aaaa). |
data | TEXT | Data da aula síncrona. |
cht | TEXT | Carga horária teórica (CHT). |
ch_planejada | TEXT | Carga horária planejada. |
professor | TEXT | Professor(a) da aula. |
conteudo_previsto | TEXT | Conteúdo previsto. |
Tabela atividades_assincronas:
| Coluna | Tipo | Descrição |
|---|---|---|
id | INTEGER | Chave primária (autoincremento). |
arquivo | TEXT | Nome do HTML de origem. |
disciplina | TEXT | Nome da disciplina. |
codigo | TEXT | Código da disciplina/turma. |
professor_disciplina | TEXT | Professor(a) da disciplina. |
semana | INTEGER | Número da semana. |
semana_inicio | TEXT | Data inicial da semana (dd/mm/aaaa). |
semana_fim | TEXT | Data final da semana (dd/mm/aaaa). |
data_inicio | TEXT | Início do período da atividade EaD. |
data_fim | TEXT | Fim do período da atividade EaD. |
ch_ead | TEXT | Carga horária EaD (CHEad). |
conteudo_previsto | TEXT | Conteúdo previsto. |
Tabela procedimentos_ensino:
| Coluna | Tipo | Descrição |
|---|---|---|
id | INTEGER | Chave primária (autoincremento). |
arquivo | TEXT | Nome do HTML de origem. |
disciplina | TEXT | Nome da disciplina. |
codigo | TEXT | Código da disciplina/turma. |
professor_disciplina | TEXT | Professor(a) da disciplina. |
atividade | TEXT | Rótulo do procedimento (ex.: "Aulas Práticas - AP"). |
descricao | TEXT | Descrição do procedimento. |
Consultando os dados
Depois de gerar os bancos, você pode consultá-los com o cliente sqlite3 ou
diretamente em Python.
- sqlite3 (CLI)
- Python
sqlite3 -header -column sincrona.db \
"SELECT semana, data, conteudo_previsto
FROM atividades_sincronas
WHERE codigo = 'ELT73A-S22'
ORDER BY semana;"
import sqlite3
con = sqlite3.connect("sincrona.db")
con.row_factory = sqlite3.Row
for r in con.execute(
"SELECT semana, data, conteudo_previsto "
"FROM atividades_sincronas ORDER BY semana"
):
print(r["semana"], r["data"], r["conteudo_previsto"])
con.close()
Saída no terminal
Ao final, o script exibe um resumo por arquivo e o total geral:
[20260807_160725.html] ELT73A-S22 - SISTEMAS MICROCONTROLADOS
Sincronas: 14 | Assincronas: 15 | Procedimentos: 5
==================== RESUMO ====================
Arquivos processados : 2
Modo : limpar (tabelas zeradas)
sincrona.db : 31 registros
assincrona.db : 15 registros
procedimentos.db : 11 registros
Bancos gravados em : /caminho/para/htmls/bancos
Os números do resumo referem-se aos registros inseridos naquela execução.
Com --no-limpar, o total dentro da tabela pode ser maior, pois os dados são
acumulados às importações anteriores.
Solução de problemas
ModuleNotFoundError: No module named 'bs4'— instale a dependência compip install beautifulsoup4.Nenhum arquivo HTML encontrado.— verifique o caminho passado em--dirou os nomes dos arquivos; sem argumentos, o script só olha o diretório atual.- Registros duplicados — provavelmente você usou
--no-limparmais de uma vez sobre os mesmos arquivos. Rode novamente no modo padrão (--limpar) para regravar do zero.
Planejamento → JSON → MDX (Docusaurus)
Pipeline que transforma os bancos SQLite gerados pelo
extrair_planejamento.py em páginas MDX do Docusaurus.
bancos/*.db ──(gerar-json.js · node:sqlite)──► src/data/*.json
src/data/*.json ──(React / gerar-mdx.js)──► docs/planejamento/*.mdx
Estrutura
.
├── package.json
├── bancos/ # coloque aqui sincrona.db, assincrona.db, procedimentos.db
├── scripts/
│ ├── gerar-json.js # SQLite -> JSON (node:sqlite embutido)
│ └── gerar-mdx.js # JSON -> páginas MDX
├── src/
│ ├── data/ # JSON gerado
│ │ ├── sincrona.json
│ │ ├── assincrona.json
│ │ ├── procedimentos.json
│ │ └── disciplinas.json # consolidado (1 objeto por disciplina)
│ └── components/
│ └── TabelaPlanejamento.jsx
└── docs/
└── planejamento/ # páginas MDX geradas
├── index.mdx
└── <slug-da-disciplina>.mdx
Pré-requisitos
- Node.js 22.5 ou superior (recomendado 24 LTS). Os scripts usam o SQLite
embutido do Node (
node:sqlite), então não há dependência nativa nem necessidade de compilar nada.
Não é necessário
npm installpara gerar o JSON/MDX — os scripts não têm dependências externas. Em versões Node 22.5–23.3, rode ogerar-json.jscom a flag--experimental-sqlite(no Node 23.4+/24 não é preciso).
Uso
Copie os três bancos para ./bancos/ e rode:
npm run gerar # gera JSON e depois as páginas MDX
# ou separadamente:
npm run gerar:json # bancos/*.db -> src/data/*.json
npm run gerar:mdx # src/data/disciplinas.json -> docs/planejamento/*.mdx
Parâmetros podem ser ajustados chamando os scripts diretamente:
node scripts/gerar-json.js --db-dir ./bancos --out ./src/data
node scripts/gerar-mdx.js --data ./src/data/disciplinas.json --out ./docs/planejamento
Formato do JSON
disciplinas.json (o mais usado pelo React) tem esta forma:
{
"geradoEm": "2026-08-17T...",
"totalDisciplinas": 2,
"disciplinas": [
{
"codigo": "ELT73A-S22",
"disciplina": "SISTEMAS MICROCONTROLADOS",
"professor": "Adriano Ruseler",
"slug": "elt73a-s22",
"sincronas": [
{
"semana": 1,
"data": "...",
"cht": 3,
"ch_planejada": 3,
"professor": "...",
"conteudo_previsto": "..."
}
],
"assincronas": [
{
"semana": 1,
"data_inicio": "...",
"data_fim": "...",
"ch_ead": 1,
"conteudo_previsto": "..."
}
],
"procedimentos": [{ "atividade": "...", "descricao": "..." }]
}
]
}
Os arquivos sincrona.json, assincrona.json e procedimentos.json trazem
cada tipo isoladamente, também agrupado por disciplina, caso você prefira
consumir um tipo por vez.
Como o React cria as páginas MDX
Cada página gerada em docs/planejamento/<slug>.mdx seleciona a disciplina
pelo slug e delega a renderização ao componente React:
---
title: SISTEMAS MICROCONTROLADOS
slug: /planejamento/elt73a-s22
---
import disciplinas from "@site/src/data/disciplinas.json";
import TabelaPlanejamento from "@site/src/components/TabelaPlanejamento";
export const disciplina = disciplinas.disciplinas.find(
(item) => item.slug === "elt73a-s22",
);
# SISTEMAS MICROCONTROLADOS
<TabelaPlanejamento disciplina={disciplina} />
O JSON permanece como única fonte de verdade: ao reprocessar os HTML e regenerar os bancos e o JSON, as páginas passam a refletir os novos dados sem edição manual.
Integração no seu projeto Docusaurus
- Copie
scripts/,src/components/TabelaPlanejamento.jsxe os JSON desrc/data/para o seu projeto Docusaurus (mantendo os caminhos). - Adicione as dependências e os scripts do
package.jsonao do seu site. - (Opcional) Rode
npm run gerar:mdxpara criar as páginas emdocs/, ou escreva suas próprias páginas MDX importando o JSON e o componente. - Se usa
sidebars.jsmanual, inclua os itens dedocs/planejamento/.