mirror of
https://github.com/fccapria/scientify.git
synced 2026-01-12 02:36:10 +00:00
Initial release
This commit is contained in:
commit
ae5e4b8873
52 changed files with 17572 additions and 0 deletions
6
backend/app/utils/nlp.py
Normal file
6
backend/app/utils/nlp.py
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import yake
|
||||
|
||||
def extract_keywords(text: str, num_keywords: int = 5) -> list:
|
||||
kw_extractor = yake.KeywordExtractor(lan="en", n=1, top=num_keywords)
|
||||
keywords = kw_extractor.extract_keywords(text)
|
||||
return [kw for kw, _ in keywords]
|
||||
165
backend/app/utils/parser.py
Normal file
165
backend/app/utils/parser.py
Normal file
|
|
@ -0,0 +1,165 @@
|
|||
import bibtexparser
|
||||
import io
|
||||
import logging
|
||||
from typing import Tuple, Optional
|
||||
from pdfminer.high_level import extract_text as pdf_extract_text
|
||||
from pdfminer.high_level import extract_text_to_fp
|
||||
import tempfile
|
||||
import os
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def bibtex(bibtex_content: str) -> Tuple[Optional[str], Optional[str], Optional[int], Optional[str], Optional[str]]:
|
||||
"""
|
||||
Estrae title, authors, year, journal, doi dal primo record di un file bibtex.
|
||||
Ritorna una tupla (title, authors, year, journal, doi).
|
||||
"""
|
||||
bib_database = bibtexparser.load(io.StringIO(bibtex_content))
|
||||
if not bib_database.entries:
|
||||
return (None, None, None, None, None)
|
||||
|
||||
entry = bib_database.entries[0]
|
||||
title = entry.get('title')
|
||||
authors = entry.get('authors') # o 'author' se il campo è diverso
|
||||
year = int(entry['year']) if 'year' in entry else None
|
||||
journal = entry.get('journal')
|
||||
doi = entry.get('doi')
|
||||
|
||||
return (title, authors, year, journal, doi)
|
||||
|
||||
|
||||
def extract_text(filename: str, content: bytes) -> str:
|
||||
"""
|
||||
🎯 FUNZIONE FONDAMENTALE: Estrae testo da file PDF per l'analisi delle keywords
|
||||
|
||||
Args:
|
||||
filename: Nome del file (per determinare il tipo)
|
||||
content: Contenuto del file in bytes
|
||||
|
||||
Returns:
|
||||
str: Testo estratto dal documento
|
||||
"""
|
||||
try:
|
||||
# Determina l'estensione del file
|
||||
file_extension = os.path.splitext(filename.lower())[1]
|
||||
|
||||
if file_extension == '.pdf':
|
||||
return extract_text_from_pdf(content)
|
||||
elif file_extension == '.docx':
|
||||
return extract_text_from_docx(content)
|
||||
elif file_extension in ['.tex', '.latex']:
|
||||
return extract_text_from_latex(content)
|
||||
else:
|
||||
logger.warning(f"Tipo di file non supportato per estrazione testo: {file_extension}")
|
||||
return ""
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Errore nell'estrazione del testo da {filename}: {e}")
|
||||
return ""
|
||||
|
||||
|
||||
def extract_text_from_pdf(pdf_content: bytes) -> str:
|
||||
"""
|
||||
Estrae testo da contenuto PDF usando pdfminer
|
||||
"""
|
||||
try:
|
||||
with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as temp_file:
|
||||
temp_file.write(pdf_content)
|
||||
temp_file.flush()
|
||||
|
||||
# Estrae il testo usando pdfminer
|
||||
text = pdf_extract_text(temp_file.name)
|
||||
|
||||
# Pulisce il file temporaneo
|
||||
os.unlink(temp_file.name)
|
||||
|
||||
logger.info(f"Estratto testo PDF: {len(text)} caratteri")
|
||||
return text or ""
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Errore nell'estrazione testo da PDF: {e}")
|
||||
return ""
|
||||
|
||||
|
||||
def extract_text_from_docx(docx_content: bytes) -> str:
|
||||
"""
|
||||
Estrae testo da contenuto DOCX usando python-docx
|
||||
"""
|
||||
try:
|
||||
from docx import Document
|
||||
|
||||
with tempfile.NamedTemporaryFile(suffix='.docx', delete=False) as temp_file:
|
||||
temp_file.write(docx_content)
|
||||
temp_file.flush()
|
||||
|
||||
# Estrae il testo usando python-docx
|
||||
doc = Document(temp_file.name)
|
||||
text_parts = []
|
||||
|
||||
for paragraph in doc.paragraphs:
|
||||
text_parts.append(paragraph.text)
|
||||
|
||||
text = '\n'.join(text_parts)
|
||||
|
||||
# Pulisce il file temporaneo
|
||||
os.unlink(temp_file.name)
|
||||
|
||||
logger.info(f"Estratto testo DOCX: {len(text)} caratteri")
|
||||
return text
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Errore nell'estrazione testo da DOCX: {e}")
|
||||
return ""
|
||||
|
||||
|
||||
def extract_text_from_latex(latex_content: bytes) -> str:
|
||||
"""
|
||||
Estrae testo da contenuto LaTeX rimuovendo i comandi LaTeX
|
||||
"""
|
||||
try:
|
||||
from pylatexenc.latex2text import LatexNodes2Text
|
||||
|
||||
# Decodifica il contenuto
|
||||
latex_text = latex_content.decode('utf-8', errors='ignore')
|
||||
|
||||
# Converte LaTeX in testo semplice
|
||||
converter = LatexNodes2Text()
|
||||
text = converter.latex_to_text(latex_text)
|
||||
|
||||
logger.info(f"Estratto testo LaTeX: {len(text)} caratteri")
|
||||
return text
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Errore nell'estrazione testo da LaTeX: {e}")
|
||||
# Fallback: rimuovi manualmente i comandi LaTeX più comuni
|
||||
try:
|
||||
latex_text = latex_content.decode('utf-8', errors='ignore')
|
||||
# Rimuove comandi LaTeX di base
|
||||
import re
|
||||
text = re.sub(r'\\[a-zA-Z]+\{[^}]*\}', '', latex_text)
|
||||
text = re.sub(r'\\[a-zA-Z]+', '', text)
|
||||
text = re.sub(r'\{[^}]*\}', '', text)
|
||||
text = re.sub(r'%.*', '', text) # Rimuove commenti
|
||||
return text.strip()
|
||||
except:
|
||||
return ""
|
||||
|
||||
|
||||
def clean_extracted_text(text: str) -> str:
|
||||
"""
|
||||
Pulisce il testo estratto per migliorare l'estrazione delle keywords
|
||||
"""
|
||||
import re
|
||||
|
||||
# Rimuove caratteri di controllo e spazi multipli
|
||||
text = re.sub(r'\s+', ' ', text)
|
||||
|
||||
# Rimuove caratteri speciali eccessivi
|
||||
text = re.sub(r'[^\w\s\-.,;:()[\]{}]', ' ', text)
|
||||
|
||||
# Rimuove linee molto corte (probabilmente header/footer)
|
||||
lines = text.split('\n')
|
||||
clean_lines = [line.strip() for line in lines if len(line.strip()) > 10]
|
||||
|
||||
return '\n'.join(clean_lines).strip()
|
||||
Loading…
Add table
Add a link
Reference in a new issue