|
"""
|
|
خدمة استخراج البنود من المستندات
|
|
"""
|
|
|
|
import re
|
|
import pandas as pd
|
|
import numpy as np
|
|
import nltk
|
|
from nltk.tokenize import sent_tokenize
|
|
from pathlib import Path
|
|
import config
|
|
|
|
class ItemExtractor:
|
|
"""استخراج البنود من المستندات"""
|
|
|
|
def __init__(self):
|
|
|
|
try:
|
|
nltk.data.find('tokenizers/punkt')
|
|
except LookupError:
|
|
nltk.download('punkt')
|
|
|
|
|
|
self.item_indicators = [
|
|
'توريد', 'تركيب', 'تنفيذ', 'تصنيع', 'أعمال', 'تأمين',
|
|
'تقديم', 'إنشاء', 'صيانة', 'إزالة', 'نقل', 'تجهيز',
|
|
'فك', 'تسليم', 'تطبيق', 'تثبيت', 'تشطيب', 'تجهيز'
|
|
]
|
|
|
|
|
|
self.categories = {
|
|
'أعمال الأساسات': ['أساس', 'قاعدة', 'حفر', 'ردم', 'خرسانة', 'اسمنت', 'قواعد'],
|
|
'أعمال الهيكل الإنشائي': ['عمود', 'سقف', 'كمرة', 'خرسانة', 'حديد تسليح', 'بلاطة', 'هيكل'],
|
|
'أعمال التشطيبات': ['دهان', 'بلاط', 'سيراميك', 'رخام', 'جبس', 'زجاج', 'باب', 'نافذة', 'أرضية'],
|
|
'أعمال الكهرباء': ['كهرباء', 'إضاءة', 'مفتاح', 'سلك', 'لوحة', 'كابل', 'تمديد'],
|
|
'أعمال السباكة': ['ماء', 'صرف', 'مواسير', 'حمام', 'مغسلة', 'خزان', 'مضخة'],
|
|
'أعمال التكييف': ['تكييف', 'تبريد', 'تهوية', 'مكيف', 'مجرى هواء', 'فلتر'],
|
|
'أعمال الموقع': ['تسوية', 'تخطيط', 'أسوار', 'بوابات', 'طرق', 'رصف', 'تشجير'],
|
|
'المستندات': ['مخططات', 'رسومات', 'تقارير', 'شهادات', 'اختبارات']
|
|
}
|
|
|
|
def extract_items(self, text):
|
|
"""استخراج البنود من النص"""
|
|
if not text:
|
|
return pd.DataFrame()
|
|
|
|
|
|
sentences = sent_tokenize(text)
|
|
|
|
|
|
items = []
|
|
item_id = 1
|
|
|
|
for sentence in sentences:
|
|
|
|
if any(indicator in sentence for indicator in self.item_indicators):
|
|
|
|
category = self._determine_category(sentence)
|
|
|
|
|
|
importance = self._determine_importance(sentence)
|
|
|
|
|
|
items.append({
|
|
'رقم البند': f"I{item_id:03d}",
|
|
'وصف البند': sentence.strip(),
|
|
'الفئة': category,
|
|
'الأهمية': importance,
|
|
'الثقة': round(np.random.uniform(0.75, 0.95), 2)
|
|
})
|
|
|
|
item_id += 1
|
|
|
|
|
|
items_df = pd.DataFrame(items)
|
|
|
|
|
|
if items_df.empty:
|
|
|
|
items_df = pd.DataFrame(columns=[
|
|
'رقم البند', 'وصف البند', 'الفئة', 'الأهمية', 'الثقة'
|
|
])
|
|
|
|
return items_df
|
|
|
|
def _determine_category(self, text):
|
|
"""تحديد فئة البند بناءً على محتواه"""
|
|
|
|
scores = {}
|
|
|
|
for category, keywords in self.categories.items():
|
|
score = sum(1 for keyword in keywords if keyword in text.lower())
|
|
scores[category] = score
|
|
|
|
|
|
if max(scores.values()) > 0:
|
|
return max(scores.items(), key=lambda x: x[1])[0]
|
|
else:
|
|
return "أخرى"
|
|
|
|
def _determine_importance(self, text):
|
|
"""تحديد أهمية البند بناءً على محتواه"""
|
|
|
|
high_importance_words = [
|
|
'ضروري', 'هام', 'أساسي', 'رئيسي', 'كبير', 'مهم',
|
|
'حرج', 'أمان', 'سلامة', 'صحة', 'بيئة'
|
|
]
|
|
|
|
|
|
low_importance_words = [
|
|
'ثانوي', 'إضافي', 'تجميلي', 'مكمل', 'اختياري'
|
|
]
|
|
|
|
|
|
high_score = sum(1 for word in high_importance_words if word in text.lower())
|
|
low_score = sum(1 for word in low_importance_words if word in text.lower())
|
|
|
|
|
|
if high_score > low_score:
|
|
return "عالية"
|
|
elif low_score > high_score:
|
|
return "منخفضة"
|
|
else:
|
|
return "متوسطة" |