Como extrair entidades nomeadas em Python para dados: passo a passo
Extrair entidades nomeadas em Python para dados permite transformar texto solto em colunas estruturadas (pessoas, organizações, locais, datas). Com esta abordagem obténs colunas que podem alimentar relatórios, criar features para modelos de Machine Learning ou automatizar etiquetagem em pipelines ETL. Vamos explicar o porquê de cada passo e mostrar como aplicar a técnica a exemplos reais, com dicas de desempenho e validação.
Pré-requisitos
- Python 3.8+ instalado
- pip para instalar pacotes
- Conhecimentos básicos de Python e pandas
- Ligaçã o à Internet para instalar spaCy e transferir um modelo
Recomendo um ambiente virtual (venv) para não conflitar com outras bibliotecas. Para conjuntos de dados pequenos (100–1 000 textos) um portátil comum chega; para milhares ou milhões de textos convém usar uma máquina com mais CPU/RAM ou paralelizar o processamento.
Passo 1: Instalar spaCy e pandas
Vamos usar spaCy para a identificação de entidades e pandas para manipular os dados. Instala os pacotes e transfere um modelo pré-treinado. O modelo en_core_web_sm é um bom ponto de partida para inglês; para português usa pt_core_news_sm.
pip install spacy pandas
python -m spacy download en_core_web_sm
# para português, usa:
# python -m spacy download pt_core_news_sm
Nota: os modelos pequenos são mais rápidos e leves, mas tendem a ser menos precisos em domínios especializados (por ex. jurídico ou médico). Se precisares de maior precisão, considera modelos maiores ou fine-tuning.
Passo 2: Preparar um DataFrame de exemplo
Cria um DataFrame com textos que queiras processar — por exemplo, descrições de notícias ou comentários. Mantém o texto numa coluna, aqui chamada text. É útil ter um id único por linha para rastreabilidade.
import pandas as pd
data = {
'id': [1, 2, 3],
'text': [
'Apple lançará o novo iPhone em Setembro em Cupertino.',
'O primeiro-ministro visitou Lisboa e o Museu Nacional ontem.',
'Tesla anuncia fábrica em Berlim prevista para 2024.'
]
}
df = pd.DataFrame(data)
print(df)
Em cenários reais podes carregar o ficheiro CSV com pd.read_csv() ou extrair de uma base de dados. Se tens 10 000+ registos, evita usar apply linha a linha sem optimização (ver Passo 4).
Passo 3: Carregar o modelo spaCy e criar função de extração
Carrega o modelo en_core_web_sm (ou outro apropriado). Cria uma função que recebe um texto e devolve uma lista de entidades com tipo e texto. Mantém a função simples para facilitar a posterior transformação em colunas.
import spacy
nlp = spacy.load('en_core_web_sm') # usa um modelo pequeno; muda se precisares de outro idioma
def extract_entities(text):
doc = nlp(text)
ents = []
for ent in doc.ents:
ents.append({'text': ent.text, 'label': ent.label_})
return ents
# Teste rápido
print(extract_entities('Barack Obama visited Berlin in 2013.'))
Dica de desempenho: se só precisares do componente NER, podes carregar com nlp = spacy.load('en_core_web_sm', exclude=['parser','tagger']) para acelerar. Para grandes volumes usa nlp.pipe no passo seguinte.
Passo 4: Aplicar a extração ao DataFrame
Usa pandas.apply para criar novas colunas com as entidades. Para conjuntos médios a grandes é mais eficiente usar nlp.pipe que processa em batch e reduz overhead do Python.
def ents_to_dict(ents):
# transforma lista de entidades em dicionário com tipos como chaves
out = {'PERSON': [], 'ORG': [], 'GPE': [], 'DATE': []}
for e in ents:
if e['label'] in out:
out[e['label']].append(e['text'])
return out
# Extrai todas as entidades
df['entities'] = df['text'].apply(extract_entities)
# Converte para dicionário de tipos
df_types = df['entities'].apply(ents_to_dict).apply(pd.Series)
# Junta ao DataFrame original
df = pd.concat([df, df_types], axis=1)
print(df[['id','text','entities','PERSON','ORG','GPE','DATE']])
Exemplo com nlp.pipe (mais eficiente para 1k+ textos):
docs = list(nlp.pipe(df['text'].astype('str')))
# depois iteras sobre docs para construir a coluna entities
Passo 5: Normalizar e limpar entidades
As entidades podem repetir-se ou ter variantes (ex.: "Lisboa" vs "Lisboa, Portugal"). Normaliza removendo duplicados, limpando espaços e transformando listas em strings separadas por vírgulas para análise/armazenamento. Também podes aplicar lematização ou usar regras para unificar formas.
def normalize_list(lst):
seen = []
for item in lst:
item = item.strip()
if item not in seen:
seen.append(item)
return ', '.join(seen) if seen else ''
for col in ['PERSON','ORG','GPE','DATE']:
df[col] = df[col].apply(normalize_list)
print(df[['id','PERSON','ORG','GPE','DATE']])
Para remover variações mais complexas, considera usar fuzzy matching (fuzzywuzzy) ou normalização por regras (regex) antes de agregares resultados.
Verificar o resultado
Confirma que as colunas novas contêm as entidades esperadas. Faz validação manual em amostras (por ex. 100 linhas) para estimar precisão e recall. Procura erros comuns: entidades vazias, etiquetas erradas por idioma ou modelos fracos.
# Visualizar linhas onde GPE (local) não está vazio
print(df[df['GPE'] != ''][['id','text','GPE']])
# Ver exemplos sem entidades detetadas
print(df[df['entities'].apply(len) == 0][['id','text']])
Se encontrares muitos falsos positivos, ajusta o modelo, usa um modelo específico de domínio ou aplica regras de pós-processamento para filtrar resultados irrelevantes.
Conclusão
Concluíste a extração de entidades nomeadas em Python para dados usando spaCy e pandas, transformando texto em colunas estruturadas prontas para análise ou features de ML. Próximos passos: testar modelos em língua portuguesa (por ex. pt_core_news_sm), ajustar pipeline para normalização (lematização, resolução de co-referência) ou armazenar resultados em CSV/SQL com df.to_csv('entities.csv', index=False) ou via SQLAlchemy. Dica final: começa por validar com amostras manuais (por ex. 100–300 exemplos) para medir a qualidade antes de automatizar em produção.