تنظيف النصوص العربية وإزالة التشكيل وحروف الجر استعداداً لتحليلها
تنظيف النصوص العربية وإزالة التشكيل وحروف الجر استعداداً لتحليلها
تُعد مرحلة تنظيف النصوص العربية من أكثر المراحل حساسية في أي مشروع يعتمد على تحليل المحتوى، لأن جودة النتائج النهائية ترتبط مباشرة بمدى دقة المعالجة المسبقة. فعند إدخال نص عربي خام إلى نموذج تصنيف، أو محرك بحث، أو نظام تحليل مشاعر، فإن وجود التشكيل، وتباين كتابة الحروف، وكثرة الكلمات الوظيفية مثل حروف الجر والعطف، قد يخلق ضوضاء تقلل من كفاءة التحليل.
في سياق علوم البيانات وهندسة البيانات، لا يُنظر إلى تنظيف النصوص كعملية تجميلية، بل كخطوة تحويل أساسية داخل خطوط أنابيب البيانات. والهدف هنا ليس فقط إزالة العناصر غير المهمة، بل توحيد البنية النصية بحيث تصبح قابلة للتجزئة، والفهرسة، والتحليل الإحصائي، ثم التحويل إلى خصائص مناسبة لنماذج Machine Learning.
هذا المقال يشرح بصورة تقنية متقدمة كيف نبني طبقة تنظيف عربية فعالة باستخدام Python وPandas وPySpark، مع التركيز على إزالة التشكيل، وتوحيد الحروف، والتخلص من حروف الجر والكلمات الشائعة، ثم تهيئة النص للتحليلات واسعة النطاق.
لماذا تحتاج النصوص العربية إلى تنظيف خاص؟
اللغة العربية تختلف عن كثير من اللغات في بنيتها الكتابية. فالكلمة الواحدة قد تظهر بصور متعددة مثل: “أحمد”، “احمد”، “أَحمد”. وإذا تُركت هذه الصيغ كما هي، فسيراها النظام كقيم مختلفة رغم أنها تشير إلى المعنى نفسه. هذا يرفع عدد السمات النصية بلا فائدة ويؤدي إلى تشتيت الإحصاءات.
كما أن النصوص العربية في البيانات الواقعية غالباً ما تأتي من مصادر غير منضبطة مثل التعليقات، والتغريدات، والدردشات، وسجلات الدعم الفني. وهذه المصادر تحتوي على مسافات غير منتظمة، ورموز، وأرقام مختلطة، وتكرار أحرف، واختلافات في كتابة الهمزات والألف المقصورة، ما يجعل المعالجة المسبقة ضرورة لا خياراً.
في البيئات التحليلية الكبيرة، تجاهل توحيد النص العربي قبل التخزين أو الفهرسة يؤدي إلى تضخم عدد القيم الفريدة داخل
DataFrameأو جداولSQL، وهذا ينعكس سلباً على الذاكرة، وسرعة التجميع، وجودة نماذج التصنيف.
أهم خطوات تنظيف النص العربي قبل التحليل
1) إزالة التشكيل والرموز الزائدة
التشكيل مثل الفتحة والضمة والكسرة والشدة يزيد من تعقيد المقارنة النصية، خاصة عندما يكون جزء من البيانات مشكولاً والجزء الآخر غير مشكول. لذلك غالباً ما تكون أول خطوة هي حذف جميع العلامات الصوتية والرموز غير الأساسية.
2) توحيد أشكال الحروف
من الممارسات المهمة تحويل “أ” و”إ” و”آ” إلى “ا”، وتحويل “ى” إلى “ي”، وتحويل “ة” حسب حالة الاستخدام إلى “ه” أو الإبقاء عليها إذا كان ذلك مهماً دلالياً. هذا النوع من التطبيع يقلل التباين الشكلي ويرفع دقة المطابقة.
3) إزالة حروف الجر والكلمات الوظيفية
حروف الجر مثل “من” و”إلى” و”على” و”في” لا تضيف في كثير من مهام التصنيف أو استخراج الموضوعات قيمة دلالية عالية، لذا تُعامل كجزء من قوائم Stopwords. ولكن يجب الحذر، لأن حذفها قد لا يكون مناسباً في كل تطبيق، مثل تحليل الأسئلة أو الاستعلامات الدقيقة.
4) تقليل التكرار وتوحيد المسافات
بعض المستخدمين يكتبون الكلمات بشكل ممتد مثل “رااائع” أو “جميللل”. ويمكن ضغط هذا التمدد إلى صيغة أقرب للأصل. كما يجب إزالة المسافات المتكررة لأن التجزئة Tokenization تعتمد على نص منظم.
تنفيذ المعالجة باستخدام بايثون وPandas
إذا كنت تعمل على ملفات متوسطة الحجم، فغالباً تبدأ من قراءة البيانات عبر Pandas ثم تطبق دوال التنظيف على عمود النص. هذا الأسلوب مناسب في النماذج الأولية، والتحليل الاستكشافي، وبناء النسخة الأولى من منطق المعالجة قبل نقله إلى بيئة موزعة.
import re
import pandas as pd
arabic_diacritics = re.compile(r'[\u0617-\u061A\u064B-\u0652]')
stopwords = {
"من", "إلى", "على", "في", "عن", "ب", "ل", "ك", "و", "يا",
"ثم", "أو", "بل", "حتى", "مع", "بين", "كان", "كانت"
}
def normalize_arabic(text):
if pd.isna(text):
return ""
text = str(text)
text = re.sub(arabic_diacritics, '', text)
text = re.sub(r'[^\u0600-\u06FF\s]', ' ', text)
text = re.sub(r'[إأآا]', 'ا', text)
text = re.sub(r'ى', 'ي', text)
text = re.sub(r'ؤ', 'و', text)
text = re.sub(r'ئ', 'ي', text)
text = re.sub(r'ة', 'ه', text)
text = re.sub(r'(.)\1{2,}', r'\1', text)
text = re.sub(r'\s+', ' ', text).strip()
tokens = text.split()
tokens = [word for word in tokens if word not in stopwords and len(word) > 1]
return " ".join(tokens)
df = pd.DataFrame({
"text": [
"ذَهَبَ العميلُ إلى المتجرِ لشراءِ منتجٍ جديد",
"التَّحليلُ النَّصي في البياناتِ العربيةِ مهمٌّ جداً",
"رااائع! هذا المنتج في غايةِ الجمال"
]
})
df["clean_text"] = df["text"].apply(normalize_arabic)
print(df)
الخطوة السابقة تمثل مرحلة Transform نموذجية داخل أي مسار معالجة. ويمكن بعد ذلك دمج النصوص المنظفة مع جداول أخرى أو استخدامها في هندسة الميزات مثل حساب التكرار، أو إنشاء TF-IDF.
معالجة النصوص العربية على نطاق ضخم باستخدام PySpark
عندما تتجاوز البيانات ملايين السجلات، تبدأ قيود الذاكرة والوقت بالظهور، وهنا ننتقل إلى Apache Spark. الفكرة الأساسية هي نقل منطق التنظيف إلى دوال قابلة للتطبيق على أعمدة موزعة داخل DataFrame بدلاً من المعالجة المتسلسلة.
import re
from pyspark.sql import SparkSession
from pyspark.sql.functions import col, udf
from pyspark.sql.types import StringType
spark = SparkSession.builder.appName("ArabicTextCleaning").getOrCreate()
arabic_diacritics = re.compile(r'[\u0617-\u061A\u064B-\u0652]')
stopwords = {
"من", "الى", "على", "في", "عن", "ب", "ل", "ك", "و",
"ثم", "او", "بل", "حتى", "مع", "بين", "كان", "كانت"
}
def normalize_text(text):
if text is None:
return ""
text = re.sub(arabic_diacritics, '', text)
text = re.sub(r'[^\u0600-\u06FF\s]', ' ', text)
text = re.sub(r'[إأآا]', 'ا', text)
text = re.sub(r'ى', 'ي', text)
text = re.sub(r'ؤ', 'و', text)
text = re.sub(r'ئ', 'ي', text)
text = re.sub(r'ة', 'ه', text)
text = re.sub(r'(.)\1{2,}', r'\1', text)
text = re.sub(r'\s+', ' ', text).strip()
tokens = [w for w in text.split() if w not in stopwords and len(w) > 1]
return " ".join(tokens)
normalize_udf = udf(normalize_text, StringType())
df = spark.createDataFrame([
(1, "ذَهَبَ العميلُ إلى المتجرِ لشراءِ منتجٍ جديد"),
(2, "التَّحليلُ النَّصي في البياناتِ العربيةِ مهمٌّ جداً"),
(3, "رااائع! هذا المنتج في غايةِ الجمال")
], ["id", "text"])
clean_df = df.withColumn("clean_text", normalize_udf(col("text")))
clean_df.show(truncate=False)
هذا الأسلوب مفيد خصوصاً عند بناء أنظمة استخراج موضوعات، أو تصنيف شكاوى العملاء، أو تنظيف بيانات محركات البحث الداخلية. وإذا كنت تبني مساراً إنتاجياً متكاملاً، فمن المناسب دمج هذه الخطوة داخل مسار ETL باستخدام PySpark مع التخزين في مستودع أو بحيرة بيانات.
في بيئات
Big Data، يُفضل تقليل استخدامUDFقدر الإمكان إذا أمكن استبدالها بدوال Spark المدمجة، لأن الدوال الأصلية أكثر كفاءة في التحسين والتنفيذ المتوازي وتقلل كلفة النقل بين طبقات التنفيذ.
استخدام SQL لفحص جودة النصوص بعد التنظيف
بعد تطبيق التنظيف، نحتاج إلى قياس الأثر عملياً. يمكن مثلاً مقارنة عدد الكلمات قبل وبعد المعالجة، أو حساب عدد القيم الفريدة، أو اكتشاف النصوص الفارغة التي أصبحت عديمة المحتوى بعد إزالة الكلمات الوظيفية. هذا مهم في مراقبة الجودة داخل مراحل Spark SQL أو مستودعات البيانات.
clean_df.createOrReplaceTempView("arabic_texts")
result = spark.sql("""
SELECT
COUNT(*) AS total_rows,
COUNT(DISTINCT text) AS raw_unique_texts,
COUNT(DISTINCT clean_text) AS cleaned_unique_texts,
SUM(CASE WHEN clean_text = '' THEN 1 ELSE 0 END) AS empty_after_cleaning
FROM arabic_texts
""")
result.show()
هذا النوع من القياس يربط تنظيف النصوص بمبادئ جودة البيانات نفسها، تماماً كما يحدث عند معالجة القيم المفقودة أو البيانات المكررة والمشوهة. فالمعالجة الصحيحة يجب أن تكون قابلة للقياس، لا مجرد تحويل صامت داخل الشيفرة.
متى تكون إزالة حروف الجر مفيدة ومتى تكون ضارة؟
ليست كل مشاريع التعامل مع البيانات النصية تستفيد من حذف حروف الجر بالكامل. ففي نماذج تصنيف الموضوعات أو تحليل المشاعر، غالباً ما يكون حذفها مفيداً لتقليل الضجيج. أما في مهام فهم النية، أو الإجابة عن الأسئلة، أو التحليل القانوني والطبي، فقد تحمل العلاقات بين الكلمات قيمة معنوية مهمة.
لذلك ينبغي بناء قائمة Stopwords مخصصة للمجال، لا الاكتفاء بقائمة عامة. النصوص التجارية تختلف عن النصوص الإخبارية، واللغة المستخدمة في منصات الدعم تختلف عن المنشورات الاجتماعية.
أفضل ممارسة معمارية هي الاحتفاظ بنسختين من النص: نسخة خام داخل طبقة التخزين الأصلية، ونسخة منظفة داخل طبقة التحليل. بهذه الطريقة يمكنك تعديل قواعد التنظيف لاحقاً دون فقدان المصدر، كما يصبح تتبع الأخطاء وإعادة المعالجة أكثر أماناً.
الخاتمة
تنظيف النصوص العربية ليس مجرد إزالة تشكيل أو حذف كلمات شائعة، بل هو عملية هندسية تؤثر في دقة النماذج، وسرعة الاستعلامات، وكفاءة التخزين، وجودة الرؤى المستخرجة من البيانات. وكلما كانت قواعد التطبيع أوضح وأكثر اتساقاً، أصبحت مراحل التحليل اللاحقة أكثر موثوقية.
ابدأ أولاً ببناء منطق التنظيف على عينة صغيرة باستخدام Pandas، ثم انقله إلى بيئة موزعة عبر PySpark عند الحاجة. وبعدها يمكنك توظيف الناتج في تطبيقات أكثر تقدماً مثل تحليل المشاعر أو بناء خصائص لغوية تدخل مباشرة في نماذج الذكاء الاصطناعي.
1 comment