import sys, os
IN_COLAB = 'google.colab' in sys.modules or os.path.exists('/content')
IN_DEEPNOTE = os.path.exists('/datasets') # pasta característica do Deepnote
if IN_COLAB or IN_DEEPNOTE:
print('Instalando dependências...')
os.system('pip install -q beautifulsoup4 sqlalchemy pandas')
print('Pronto.')
else:
print('Ambiente local detectado — certifique-se de ter rodado: pip install -r requirements.txt')
Run to view results
import urllib.request
import urllib.error
import re
import time
import datetime
import os
import pandas as pd
from bs4 import BeautifulSoup
from sqlalchemy import create_engine, text
# ── Pasta e banco de dados ───────────────────────────────────────────────
DB_DIR = 'banco'
DB_PATH = os.path.join(DB_DIR, 'linguagens.db')
os.makedirs(DB_DIR, exist_ok=True)
ENGINE = create_engine(f'sqlite:///{DB_PATH}', echo=False)
# ── Cabeçalho HTTP ───────────────────────────────────────────────────────
HEADERS = {
'User-Agent': (
'Mozilla/5.0 (compatible; ProjetoInfnet/1.0; '
'+https://www.infnet.edu.br)'
)
}
# ── URL de entrada (Nível 1) ─────────────────────────────────────────────
URL_INDICE = 'https://en.wikipedia.org/wiki/List_of_programming_languages'
# ── Escopo do projeto ────────────────────────────────────────────────────
INICIAIS_PERMITIDAS = set('CJP') # Apenas linguagens começando por C, J e P
MAX_LINGUAGENS = 40 # Limite de segurança
print(f'Engine: {ENGINE.url}')
print(f'Iniciais: {sorted(INICIAIS_PERMITIDAS)} | Limite: {MAX_LINGUAGENS} linguagens')
Run to view results
def criar_tabelas(engine):
"""Cria as três tabelas do projeto, se ainda não existirem."""
with engine.connect() as conn:
conn.execute(text("""
CREATE TABLE IF NOT EXISTS linguagens (
id INTEGER PRIMARY KEY AUTOINCREMENT,
nome TEXT,
ano_criacao INTEGER,
criador TEXT,
paradigma TEXT,
tipagem TEXT,
url_wikipedia TEXT
)
"""))
conn.execute(text("""
CREATE TABLE IF NOT EXISTS paginas_visitadas (
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT,
http_status INTEGER,
timestamp TEXT,
linguagem_id INTEGER,
FOREIGN KEY (linguagem_id) REFERENCES linguagens(id)
)
"""))
conn.execute(text("""
CREATE TABLE IF NOT EXISTS erros_scraping (
id INTEGER PRIMARY KEY AUTOINCREMENT,
url TEXT,
tipo_erro TEXT,
mensagem TEXT,
timestamp TEXT
)
"""))
print('Tabelas criadas (ou já existentes).')
criar_tabelas(ENGINE)
Run to view results
def timestamp_agora():
"""Retorna o momento atual como string ISO."""
return datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')
def baixar_pagina(url):
"""
Faz o download de uma página via urllib.
Retorna (html_bytes, http_status).
Lança urllib.error.HTTPError ou urllib.error.URLError em caso de falha.
"""
req = urllib.request.Request(url, headers=HEADERS)
with urllib.request.urlopen(req, timeout=10) as resp:
status = resp.status
html = resp.read()
return html, status
def registrar_visita(url, status, linguagem_id=None):
"""Grava um registro na tabela paginas_visitadas."""
df = pd.DataFrame([{
'url': url,
'http_status': status,
'timestamp': timestamp_agora(),
'linguagem_id': linguagem_id,
}])
df.to_sql('paginas_visitadas', ENGINE, if_exists='append', index=False)
def registrar_erro(url, excecao):
"""Grava um registro na tabela erros_scraping."""
df = pd.DataFrame([{
'url': url,
'tipo_erro': type(excecao).__name__,
'mensagem': str(excecao),
'timestamp': timestamp_agora(),
}])
df.to_sql('erros_scraping', ENGINE, if_exists='append', index=False)
print('Funções utilitárias definidas.')
Run to view results
# 4 Atividades do Projeto
# 4.1 :
try:
html, status = baixar_pagina(URL_INDICE)
registrar_visita(URL_INDICE, status)
soup = BeautifulSoup(html, 'html.parser')
print("Página índice baixada com sucesso. Status:", status)
except Exception as e:
registrar_erro(URL_INDICE, e)
print("Erro ao baixar página índice:", e)
Run to view results
#4.1
links_linguagens = []
try:
for li in soup.select('div.mw-parser-output ul li'):
a = li.find('a')
if a and a.get('href', '').startswith('/wiki/'):
nome = a.text.strip()
if nome and nome[0].upper() in INICIAIS_PERMITIDAS:
url = 'https://en.wikipedia.org' + a['href']
links_linguagens.append((nome, url))
print(f'Foram encontrados {len(links_linguagens)} links de linguagens C, J e P.')
print("Exemplo dos primeiros links:", links_linguagens[:10])
except Exception as e:
registrar_erro(URL_INDICE, e)
print("Erro ao extrair links:", e)
Run to view results
#4.1
def extrair_dados_linguagem(nome, url):
try:
html, status = baixar_pagina(url)
registrar_visita(url, status)
soup = BeautifulSoup(html, 'html.parser')
infobox = soup.find('table', class_=lambda c: c and 'infobox' in c)
if not infobox:
raise AttributeError("Infobox não encontrado")
ano_criacao, criador, paradigma, tipagem = None, None, None, None
for tr in infobox.find_all('tr'):
th = tr.find('th')
td = tr.find('td')
if not th or not td:
continue
chave = th.text.strip().lower()
valor = td.text.strip()
if 'designed' in chave or 'developer' in chave or 'created' in chave:
criador = valor
elif 'first appeared' in chave or 'year' in chave:
match = re.search(r'\d{4}', valor)
if match:
ano_criacao = int(match.group())
elif 'paradigm' in chave:
paradigma = valor
elif 'typing' in chave:
tipagem = valor
df = pd.DataFrame([{
'nome': nome,
'ano_criacao': ano_criacao,
'criador': criador,
'paradigma': paradigma,
'tipagem': tipagem,
'url_wikipedia': url
}])
df.to_sql('linguagens', ENGINE, if_exists='append', index=False)
print(f"Linguagem {nome} inserida com sucesso.")
except Exception as e:
registrar_erro(url, e)
print(f"Erro ao processar {nome}: {e}")
Run to view results
#4.1
def extrair_dados_linguagem(nome, url):
try:
html, status = baixar_pagina(url)
registrar_visita(url, status)
soup = BeautifulSoup(html, 'html.parser')
infobox = soup.find('table', class_=lambda c: c and 'infobox' in c)
if not infobox:
raise AttributeError("Infobox não encontrado")
ano_criacao, criador, paradigma, tipagem = None, None, None, None
for tr in infobox.find_all('tr'):
th = tr.find('th')
td = tr.find('td')
if not th or not td:
continue
chave = th.text.strip().lower()
valor = td.text.strip()
if 'designed' in chave or 'developer' in chave or 'created' in chave:
criador = valor
elif 'first appeared' in chave or 'year' in chave:
match = re.search(r'\d{4}', valor)
if match:
ano_criacao = int(match.group())
elif 'paradigm' in chave:
paradigma = valor
elif 'typing' in chave:
tipagem = valor
df = pd.DataFrame([{
'nome': nome,
'ano_criacao': ano_criacao,
'criador': criador,
'paradigma': paradigma,
'tipagem': tipagem,
'url_wikipedia': url
}])
df.to_sql('linguagens', ENGINE, if_exists='append', index=False)
print(f"Linguagem {nome} inserida com sucesso.")
except Exception as e:
registrar_erro(url, e)
print(f"Erro ao processar {nome}: {e}")
Run to view results
#4.1
for nome, url in links_linguagens[:MAX_LINGUAGENS]:
extrair_dados_linguagem(nome, url)
Run to view results
# Exercicio 4.2
def extrair_dados_linguagem(nome, url):
try:
html, status = baixar_pagina(url)
registrar_visita(url, status)
soup = BeautifulSoup(html, 'html.parser')
infobox = soup.find('table', class_=lambda c: c and 'infobox' in c)
if not infobox:
try:
raise AttributeError("Infobox não encontrado")
except AttributeError as e:
registrar_erro(url, e)
print(f"Erro esperado em {nome}: {e}")
pass
return
ano_criacao, criador, paradigma, tipagem = None, None, None, None
for tr in infobox.find_all('tr'):
th = tr.find('th')
td = tr.find('td')
if not th or not td:
continue
chave = th.text.strip().lower()
valor = td.text.strip()
if 'designed' in chave or 'developer' in chave or 'created' in chave:
criador = valor
elif 'first appeared' in chave or 'year' in chave:
match = re.search(r'\d{4}', valor)
if match:
ano_criacao = int(match.group())
elif 'paradigm' in chave:
paradigma = valor
elif 'typing' in chave:
tipagem = valor
df = pd.DataFrame([{
'nome': nome,
'ano_criacao': ano_criacao,
'criador': criador,
'paradigma': paradigma,
'tipagem': tipagem,
'url_wikipedia': url
}])
df.to_sql('linguagens', ENGINE, if_exists='append', index=False)
print(f"Linguagem {nome} inserida com sucesso.")
except Exception as e:
registrar_erro(url, e)
print(f"Erro ao processar {nome}: {e}")
Run to view results
# Exercicio 4.3
df_linguagens = pd.read_sql("SELECT * FROM linguagens", ENGINE)
print("Tabela linguagens:")
print(df_linguagens.head())
df_paginas = pd.read_sql("SELECT * FROM paginas_visitadas", ENGINE)
print("\nTabela paginas_visitadas:")
print(df_paginas.head())
df_erros = pd.read_sql("SELECT * FROM erros_scraping", ENGINE)
print("\nTabela erros_scraping:")
print(df_erros.head())
Run to view results
# 4.3
print("Total de linguagens inseridas:", len(df_linguagens))
print("Total de páginas visitadas:", len(df_paginas))
print("Total de erros registrados:", len(df_erros))
Run to view results
# Exercicio 4.4
consulta1 = pd.read_sql("""
SELECT *
FROM linguagens
WHERE ano_criacao >= 1990
""", ENGINE)
print("Consulta 1 — Linguagens criadas a partir de 1990:")
print(consulta1.head())
Run to view results
#4.4
consulta2 = pd.read_sql("""
SELECT *
FROM erros_scraping
""", ENGINE)
print("\nConsulta 2 — Linguagens que geraram erros durante o scraping:")
print(consulta2.head())
Run to view results
#4.4
consulta3 = pd.read_sql("""
SELECT paradigma,
COUNT(*) AS total_linguagens,
SUM(CASE WHEN paradigma IS NOT NULL THEN 1 ELSE 0 END) AS sucesso,
ROUND(
100.0 * SUM(CASE WHEN paradigma IS NOT NULL THEN 1 ELSE 0 END) / COUNT(*),
2
) AS taxa_sucesso
FROM linguagens
GROUP BY paradigma
ORDER BY taxa_sucesso DESC
""", ENGINE)
print("\nConsulta 3 — Taxa de sucesso do scraping por paradigma:")
print(consulta3.head())
Run to view results
# Exercicio 4.5
total_paginas = pd.read_sql("SELECT COUNT(*) AS total FROM paginas_visitadas", ENGINE)
print("Total de paginas visitadas:")
print(total_paginas)
total_erros = pd.read_sql("SELECT COUNT(*) AS total FROM erros_scraping", ENGINE)
print("\nTotal de erros registrados:")
print(total_erros)
Run to view results
#4.5
erros_por_tipo = pd.read_sql("""
SELECT tipo_erro, COUNT(*) AS quantidade
FROM erros_scraping
GROUP BY tipo_erro
ORDER BY quantidade DESC
""", ENGINE)
print("\nDistribuição de erros por tipo de exceção:")
print(erros_por_tipo)
Run to view results
#4.5
linguagens_por_paradigma = pd.read_sql("""
SELECT paradigma, COUNT(*) AS quantidade
FROM linguagens
GROUP BY paradigma
ORDER BY quantidade DESC
""", ENGINE)
print("\nQuantidade de linguagens por paradigma:")
print(linguagens_por_paradigma)
Run to view results
#4.5
consulta1 = pd.read_sql("""
SELECT *
FROM linguagens
WHERE ano_criacao >= 1990
""", ENGINE)
consulta2 = pd.read_sql("""
SELECT *
FROM erros_scraping
""", ENGINE)
consulta3 = pd.read_sql("""
SELECT paradigma,
COUNT(*) AS total_linguagens,
SUM(CASE WHEN paradigma IS NOT NULL THEN 1 ELSE 0 END) AS sucesso,
ROUND(
100.0 * SUM(CASE WHEN paradigma IS NOT NULL THEN 1 ELSE 0 END) / COUNT(*),
2
) AS taxa_sucesso
FROM linguagens
GROUP BY paradigma
ORDER BY taxa_sucesso DESC
""", ENGINE)
print("\nConsulta 1 — Linguagens criadas a partir de 1990:")
print(consulta1.head())
print("\nConsulta 2 — Linguagens que geraram erros:")
print(consulta2.head())
print("\nConsulta 3 — Taxa de sucesso por paradigma:")
print(consulta3.head())
Run to view results