ai-news-api / src /preprocessing /text_cleaner.py
vinitsingare's picture
feat: Add Explainable AI (XAI) and fix DistilBERT dataset bias
6197db3
Raw
History Blame Contribute Delete
3.32 kB
import re
import string
import nltk
import spacy
from nltk.corpus import stopwords
from nltk.stem import PorterStemmer
from src.ingestion.database import get_session, Article
# Download required NLTK components
try:
nltk.data.find('corpora/stopwords')
except LookupError:
nltk.download('stopwords')
try:
nltk.data.find('tokenizers/punkt')
except LookupError:
nltk.download('punkt')
# Load or download the spaCy English model
try:
nlp = spacy.load("en_core_web_sm")
except OSError:
print("Downloading spacy model 'en_core_web_sm'...")
from spacy.cli import download
download("en_core_web_sm")
nlp = spacy.load("en_core_web_sm")
# Initialize global tools
stop_words = set(stopwords.words('english'))
stemmer = PorterStemmer()
def clean_text(text: str, apply_stemming: bool = False, apply_lemmatization: bool = True) -> str:
"""
Cleans raw text data using a standard NLP pipeline.
Includes lowercasing, punctuation removal, stopword removal, stemming, and lemmatization.
"""
if not text or not isinstance(text, str):
return ""
# 1. Lowercase
text = text.lower()
# 2. Punctuation removal
text = text.translate(str.maketrans('', '', string.punctuation))
# 3. Noise removal (numbers and extra whitespace)
text = re.sub(r'\d+', '', text)
text = re.sub(r'\s+', ' ', text).strip()
# 4. Tokenization & Stopword removal (NLTK)
tokens = [word for word in text.split() if word not in stop_words]
# 5. Stemming (Porter)
if apply_stemming and not apply_lemmatization:
tokens = [stemmer.stem(word) for word in tokens]
return " ".join(tokens)
# 6. Lemmatization (spaCy)
if apply_lemmatization:
doc = nlp(" ".join(tokens))
lemmas = [token.lemma_ for token in doc]
return " ".join(lemmas)
return " ".join(tokens)
def process_uncleaned_articles():
"""
Fetches raw articles from the database, applies the NLP cleaning pipeline,
and saves the cleaned text back to the database.
"""
session = get_session()
try:
# Fetch articles that haven't been cleaned yet
uncleaned_articles = session.query(Article).filter(
(Article.clean_content == None) | (Article.clean_content == "")
).all()
print(f"Found {len(uncleaned_articles)} articles pending NLP preprocessing...")
processed_count = 0
for article in uncleaned_articles:
if article.raw_content:
cleaned = clean_text(article.raw_content)
article.clean_content = cleaned
processed_count += 1
session.commit()
print(f"Successfully cleaned and updated {processed_count} articles.")
return processed_count
except Exception as e:
session.rollback()
print(f"Error during preprocessing: {e}")
return 0
finally:
session.close()
if __name__ == "__main__":
# Test on a dummy string
sample = "Apple IS looking at buying U.K. startup for $1 billion! 123"
print("Original:", sample)
print("Cleaned:", clean_text(sample))
# Run bulk processing
print("\nRunning database preprocessing...")
process_uncleaned_articles()