20 KiB
دستورالعمل جامع نرمالسازی جستجو برای متون عربی و اسلامی
(Comprehensive Arabic & Persian Search Normalization Specification)
۱. مقدمه و بیان مسئله (Executive Summary & Problem Statement)
در پایگاههای داده و سامانههای متنی اسلامی و حدیثی، جستجوی متنی با چالشهای بنیادین زبانشناختی و فنی مواجه است:
- گوناگونی رسمالخط و کدگذاری یونیکد (Unicode Homoglyphs): نویسههایی مانند الف همزهدار (
أ،إ)، الف ممدوده (آ)، الف وصل (ٱ) و الف ساده (ا) دارای کدهای یونیکد کاملاً متفاوتی هستند. - اعراب و اعجام (Harakat / Tashkeel): متون احادیث و اسناد دینی معمولاً با حرکتگذاری کامل (مانند
إِنَّمَا الأَعْمَالُ) در پایگاه داده ذخیره شدهاند، در حالی که کاربران جستجوهای خود را بدون اعراب (انما الاعمالیاانما) تایپ میکنند. در مقایسههای متنی پیشفرض دیتابیس (LIKEیاILIKEوicontains)، وجود اعراب در میان حروف کلمه باعث میشود کلمه کاربر تطبیق داده نشود و نتیجه «هیچ رکوردی یافت نشد» برگردد. - تداخل کاراکترهای فارسی و عربی: در کیبوردهای کاربران (موبایل و دسکتاپ)، حروفی چون «ی» و «ي»، «ک» و «ك»، «ه» و «ة» مدام جابهجا میشوند.
- علائم قرآنی و وقوف: نمادهایی مانند «الف خنجری» (
ٰمانندرَحْمٰنِ)، علائم وقف و نمادهای تعظیم اگر نرمال نشوند، جستجو را مسدود میکنند.
هدف: هر متنی که کاربر با هر شکلی از کیبورد (با اعراب، بدون اعراب، با همزه یا بدون همزه، فارسی یا عربی) جستجو کرد، سیستم باید دقیقاً مفهوم آن را درک کرده و تمامی رکوردهای منطبق را بدون وابستگی به شکل ظاهری نگارش پیدا کند.
۲. دستهبندی جامع کاراکترها و حالات نرمالسازی (Normalization Taxonomy)
۲.۱. خانواده الفها و همزهها (Alef & Hamza Variants)
الف در رسمالخط عربی دارای حالتهای متعددی است که در جستجو باید همگی یکپارچه شوند:
| نویسه اصلی | نام یونیکد | کد یونیکد | هدف نرمالسازی | مثال جستجو | مثال در دیتابیس |
|---|---|---|---|---|---|
| أ | Arabic Letter Alef With Hamza Above | U+0623 |
ا (U+0627) |
أنما | انما / إِنَّمَا |
| إ | Arabic Letter Alef With Hamza Below | U+0625 |
ا (U+0627) |
إسناد | اسناد |
| آ | Arabic Letter Alef With Madda Above | U+0622 |
ا (U+0627) |
آثار | اثار |
| ٱ | Arabic Letter Alef Wasla | U+0671 |
ا (U+0627) |
ٱمرؤ | امرؤ |
| ا | Arabic Letter Alef (Bare) | U+0627 |
ا (U+0627) |
اعمال | أعمال |
| ٴ | Arabic Letter High Hamza | U+0674 |
حذف یا ا | — | — |
حالات دیگر همزهها (Other Hamza Forms):
- همزه روی واو (
ؤ-U+0624): در جستجوی آسانگیر (Lenient)، همزه روی واو بهو(U+0648) نرمال میشود تا کاربر با سرچ «مومن» بتواند «مؤمن» را پیدا کند یا بالعکس («مسؤول» / «مسئول»). - همزه روی یاء / نبره (
ئ-U+0626): بهی/يتبدیل میشود تا کلماتی چون «قائل»، «قایل»، «هیئة»، «هيئة» همارز شوند. - همزه تنها روی خط (
ء-U+0621): حذف یا تبدیل به فاصله در صورت نیاز.
۲.۲. خانواده یاء و الف مقصوره (Yeh & Alef Maksura)
یکی از پرتکرارترین خطاها در جستجوی عربی و فارسی مربوط به حرف «ی» است:
| نویسه اصلی | نام | کد یونیکد | رفتار نرمالسازی | مثال |
|---|---|---|---|---|
| ي | یاء عربی دو نقطه | U+064A |
تبدیل به نویسه واحد مبنا (مثلاً ی یا ي) |
علي / علی |
| ى | الف مقصوره عربی (بینقطه) | U+0649 |
تبدیل به ی یا ا بر اساس سیاست پروژه |
موسی / موسي / موسى |
| ی | یای فارسی بدون نقطه | U+06CC |
تبدیل به نویسه واحد مبنا | حدیث / حديث |
| ئ | یاء با همزه | U+0626 |
تبدیل به نویسه واحد مبنا | بئر / بیر |
نکته تخصصی در متون دینی: الف مقصوره (
ىدر انتهای کلماتی چون «حتى»، «إلى»، «موسى») در کیبورد کاربران گاهی بای، گاهی بايو حتی گاهی به اشتباه باا(«حتا») نوشته میشود. نرمالسازی[ي ى ی ئ]به یک نویسه پایدار، پوشش جستجو را به ۱۰۰٪ میرساند.
۲.۳. کاف عربی و فارسی (Kaf Normalization)
- ك (کاف عربی با نشان همزه/کاف کوچک:
U+0643) - ک (کاف فارسی سرکشدار:
U+06A9) - قاعده: تبدیل هر دو به یک فرم استاندارد (مثلاً
كبرای متون عربی یاک).
۲.۴. تاء مربوطه و هاء (Teh Marbuta & Heh)
- ة (تاء مربوطه:
U+0629) - ه (هاء:
U+0647) - ۀ (هاء با همزه:
U+06C0) - تحلیل رفتاری: کاربران در تایپ سریع اسامی یا اصطلاحات اغلب تاء مربوطه را با هاء جابهجا میزنند:
- «معاویه» ↔ «معاوية»
- «فاطمه» ↔ «فاطمة»
- «صحابه» ↔ «صحابة»
- «رواة» ↔ «رواه»
- قاعده سرچ نرمال: برای جستجوی متنی،
ةبههتبدیل میشود تا تفاوت نگارشی کاربر باعث حذف رکورد نشود.
۲.۵. حرکات، اعراب و تنوینها (Tashkeel / Harakat / Diacritics) - حیاتیترین بخش
تمام حرکات زیر باید از متن ورودی و از نسخه ایندکسشده جستجو کاملاً حذف شوند:
| نام حرکت | علامت | کد یونیکد | اثر در جستجوی خام دیتابیس |
|---|---|---|---|
| فتحه (Fatha) | َ | U+064E |
مانع تطابق متن ساده میشود |
| ضمه (Damma) | ُ | U+064F |
مانع تطابق متن ساده میشود |
| کسره (Kasra) | ِ | U+0650 |
مانع تطابق متن ساده میشود |
| تنوین نصب (Fathatan) | ً | U+064B |
مانع تطابق |
| تنوین رفع (Dammatan) | ٌ | U+064C |
مانع تطابق |
| تنوین جر (Kasratan) | ٍ | U+064D |
مانع تطابق |
| سکون (Sukun) | ْ | U+0652 |
مانع تطابق |
| تشدید (Shadda) | ّ | U+0651 |
مانع تطابق کلمات دارای تشدید |
| الف خنجری (Dagger Alef) | ٰ | U+0670 |
بسیار خطرناک: در «رَحْمٰنِ»، «إِلٰهَ»، «هٰذَا»، «إِسْمٰعِيل» اگر حذف نشود، سرچ «رحمن» هرگز «رحمٰن» را پیدا نمیکند! |
| مده (Maddah) | ٓ | U+0653 |
مانع تطابق |
| همزه فوقانی اعرابی | ٔ | U+0654 |
مانع تطابق |
| همزه تحتانی اعرابی | ٕ | U+0655 |
مانع تطابق |
۲.۶. کشیدگی، تطویل و نشانههای نامرئی (Tatweel & Invisible Characters)
- تطویل / کشیده (
ـ-U+0640): برای تنظیم طول خطوط در متون کهن یا زیبایی متنی به کار میرود (مثلصـــــراطیارســــول). این کاراکتر باید به کلی حذف شود. - نیمفاصله (Zero-Width Non-Joiner -
U+200C): در متون فارسی و اسامی ترکیبی وجود دارد؛ باید به فاصله عادی یا حذف کامل تبدیل شود. - اتصالدهنده مجازی (ZWJ -
U+200D): باید حذف شود. - نشانگرهای جهت یونیکد (LRM
U+200Eو RLMU+200F): باید کاملاً حذف شوند.
۲.۷. نشانهها و نمادهای وقوف قرآنی و مذهبی (Quranic Symbols & Waqf Marks)
در متون روایی و قرآنی نمادهای ویژهای در یونیکد ذخیره میشوند که باید در لایه سرچ پالایش گردند:
- علائم وقف قرآنی:
ۖ(U+06D6),ۗ(U+06D7),ۘ(U+06D8),ۙ(U+06D9),ۚ(U+06DA),ۛ(U+06DB),ۜ(U+06DC),(U+06DD),۞(U+06DE),۟(U+06DF),۠(U+06E0),ۡ(U+06E1),ۢ(U+06E2),ۣ(U+06E3),ۤ(U+06E4). - نمادهای لیگچر مذهبی:
ﷺ(U+FDFA),ﷻ(U+FDFB),﷽(U+FDFD),ؑ(U+0611). - پرانتزها و براکتهای قرآنی و نقلقول:
﴿،﴾،«،»،[،]،(،).
۲.۸. ارقام و اعداد (Digits)
- ارقام عربی-مشرقی:
[٠, ١, ٢, ٣, ٤, ٥, ٦, ٧, ٨, ٩] - ارقام فارسی:
[۰, ۱, ۲, ۳, ۴, ۵, ۶, ۷, ۸, ۹] - ارقام استاندارد لاتین:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9] - قاعده: تبدیل تمام ارقام به ارقام استاندارد (0-9) تا سرچ شماره حدیث یا جلد و صفحه فارغ از نوع کیبورد عدد را پیدا کند.
۳. ماتریس مقایسهای سناریوهای سرچ (Search Scenario Matrix)
| ورودی کاربر در سرچ | متن در دیتابیس | وضعیت جستجوی فعلی (خام) | وضعیت پس از نرمالسازی |
|---|---|---|---|
انما |
أنما الأعمال بالنيات |
❌ No result (تفاوت ا و أ) |
✅ منطبق و پیدا میشود |
انما |
إِنَّمَا الأَعْمَالُ بِالنِّيَّاتِ |
❌ No result (وجود کسره، تشدید، فتحه) | ✅ منطبق و پیدا میشود |
أبو هريرة |
ابو هريره |
❌ No result (تفاوت أ/ا و ة/ه) |
✅ منطبق و پیدا میشود |
صحیح بخاری |
صَحِيحُ الْبُخَارِيِّ |
❌ No result (تفاوت اعراب، ی/ي) |
✅ منطبق و پیدا میشود |
رحمن |
الرَّحْمٰنِ الرَّحِيمِ |
❌ No result (وجود الف خنجری ٰ) |
✅ منطبق و پیدا میشود |
مومن |
إِنَّمَا الْمُؤْمِنُونَ إِخْوَةٌ |
❌ No result (تفاوت و با ؤ) |
✅ منطبق و پیدا میشود |
صراط |
صــــراط الذين |
❌ No result (وجود کشیده ـ) |
✅ منطبق و پیدا میشود |
حدیث ۱۱۰ |
حديث 110 یا حديث ١١٠ |
❌ No result (تفاوت ارقام) | ✅ منطبق و پیدا میشود |
۴. گزینهها و معماری پیادهسازی فنی در Django و PostgreSQL
برای اعمال این نرمالسازی در سیستم، سه رویکرد معماری وجود دارد:
🟢 گزینه اول: الگوی ستون جستجوی نرمالشده (Normalized Shadow Column / Search Column) — [رویکرد پیشنهادی و استاندارد]
در این الگو، متن اصلی برای نمایش دستنخورده باقی میماند (تا اعراب و زیبایی اصیل آن در UI حفظ شود)، اما یک ستون متنی نرمالشده در کنار آن ایجاد و ایندکسگذاری میشود:
- در مدلها (
Hadis،HadisCategory،Transmitterو ...):- افزودن فیلد
normalized_text = models.TextField(blank=True, db_index=True)یا استفاده ازdjango.contrib.postgres.search.SearchVector. - در متد
save()مدل، متن اصلی از تابع نرمالساز عبور کرده و فیلد نرمالشده به صورت خودکار پر میشود. - ایجاد یک اسکریپت ساده migration برای پر کردن یکباره مقادیر رکوردهای موجود.
- افزودن فیلد
- در لایه Queryset / View:
- عبارت سرچ کاربر (
search_query) توسط همان تابع پایتون نرمالسازی میشود:normalized_q = normalize_text(search_query). - جستجو روی ستون
normalized_text__icontains=normalized_qانجام میشود.
- عبارت سرچ کاربر (
- مزایا:
- فوقالعاده سریع (High Performance): دیتابیس مستقیماً روی ستون ایندکسشده کوئری میزند بدون اینکه در هر ریکوئست تابع یا رجکس سنگین روی میلیونها کاراکتر اجرا شود.
- سادگی و پایداری: سازگاری کامل با معماری فعلی Django بدون نیاز به نصب اکستنشنهای پیچیده C در دیتابیس سرور.
- دقت ۱۰۰٪: تضمین میکند که منطق سمت پایتون در هر دو طرف ذخیره و جستجو دقیقاً یکی است.
🟡 گزینه دوم: تابع پایگاه داده در سطح PostgreSQL (Database-Level Stored Function & Functional Index)
- ایجاد یک تابع PL/pgSQL در PostgreSQL (مثلاً
fn_normalize_arabic(text)). - ساخت ایندکس تابعی:
CREATE INDEX idx_hadis_normalized_text ON hadis_hadis (fn_normalize_arabic(text)); - در جنگو با استفاده از
Funcیا Raw SQL:queryset.filter(Q(normalized_text_func__icontains=normalize_text(query))) - مزایا: عدم نیاز به ذخیره دیتای مضاعف در ستون جداگانه.
- معایب: وابستگی شدید به دیتابیس، سختی مایگریشن در محیطهای توسعه و تست SQLite/Docker، و پیچیدگی نگهداری لاجیک در SQL.
🔴 گزینه سوم: استفاده از Regex در زمان کوئری (Query-time Regex)
- تبدیل هر حرف از کلمه سرچ به یک گروه رجکس؛ مثلاً تبدیل
انمابه:[اأإآٱ][ًٌٍَُِّْٰ]*ن[ًٌٍَُِّْٰ]*م[ًٌٍَُِّْٰ]*[اأإآٱ] - ارسال به دیتابیس با
text__iregex=pattern. - معایب:
- بسیار کند: دیتابیس نمیتواند از هیچ ایندکسی استفاده کند (Full Table Scan با Regex Engine).
- با افزایش تعداد احادیث و اسناد، پاسخ سرور از چند میلیثانیه به چند ثانیه افزایش مییابد و بار سرور را به شدت بالا میبرد.
۵. کد مرجع پایتون برای تابع نرمالسازی (Python Reference Implementation)
این تابع کاملترین و بهینهترین پیادهسازی منطبق با استاندارد Unicode Consortium برای متون عربی و فارسی است:
import re
import unicodedata
# 1. حرکات، اعراب، تنوینها، تشدید، سکون و الف خنجری
# شامل بازه U+064B تا U+065F و الف مقصوره بالایی U+0670
ARABIC_DIACRITICS_REGEX = re.compile(r'[\u064B-\u065F\u0670\u06D6-\u06ED]')
# 2. کاراکتر کشیدگی / تطویل
TATWEEL_REGEX = re.compile(r'\u0640')
# 3. جدول نگاشت الفها و کاراکترهای چندشکلی
ARABIC_NORMALIZATION_MAP = str.maketrans({
# انواع الف به الف ساده
'أ': 'ا',
'إ': 'ا',
'آ': 'ا',
'ٱ': 'ا',
# انواع یاء و الف مقصوره به یای استاندارد
'ي': 'ی',
'ى': 'ی',
'ئ': 'ی',
# کاف عربی به کاف یکسان
'ك': 'ک',
# تاء مربوطه و هاء
'ة': 'ه',
'ۀ': 'ه',
# واو همزهدار
'ؤ': 'و',
# ارقام عربی مشرقی و فارسی به ارقام استاندارد
'٠': '0', '١': '1', '٢': '2', '٣': '3', '٤': '4',
'٥': '5', '٦': '6', '٧': '7', '٨': '8', '٩': '9',
'۰': '0', '۱': '1', '۲': '2', '۳': '3', '۴': '4',
'۵': '5', '۶': '6', '۷': '7', '۸': '8', '۹': '9',
})
# 4. کاراکترهای کنترلی و نامرئی (Zero-width spaces, LRM, RLM)
ZERO_WIDTH_REGEX = re.compile(r'[\u200B-\u200F\u202A-\u202E\uFEFF]')
def normalize_for_search(text: str) -> str:
"""
متن ورودی را بر اساس قواعد استاندارد جستجوی متون عربی و اسلامی نرمالسازی میکند:
1. حذف کاراکترهای کنترلی پنهان و نیمفاصلههای نامتعارف
2. حذف کامل تمام اعرابها، حرکات، تشدید، تنوینها و الف خنجری (Tashkeel)
3. حذف علامت کشیدگی (تطویل / کشیده)
4. یکسانسازی الفها (أ، إ، آ، ٱ -> ا)
5. یکسانسازی یاء و الف مقصوره (ي، ى، ئ -> ی)
6. یکسانسازی کاف (ك -> ک)
7. یکسانسازی تاء مربوطه (ة -> ه)
8. یکسانسازی واو همزهدار (ؤ -> و)
9. تبدیل ارقام عربی و فارسی به ارقام استاندارد
10. یکپارچهسازی فاصلههای خالی چندگانه
"""
if not text or not isinstance(text, str):
return ""
# ۱. نرمالسازی فرم یونیکد (NFKC)
text = unicodedata.normalize('NFKC', text)
# ۲. حذف کاراکترهای نامرئی
text = ZERO_WIDTH_REGEX.sub('', text)
# ۳. حذف حرکات و اعراب
text = ARABIC_DIACRITICS_REGEX.sub('', text)
# ۴. حذف تطویل
text = TATWEEL_REGEX.sub('', text)
# ۵. نگاشت الفها و کاراکترهای همارز
text = text.translate(ARABIC_NORMALIZATION_MAP)
# ۶. حذف فاصلههای اضافی مکرر
text = re.sub(r'\s+', ' ', text).strip()
return text
۶. نقشه راه اجرایی پیشنهادی (Recommended Implementation Roadmap)
- فاز ۱ — بررسی و تأیید نهایی:
- تأیید قوانین نرمالسازی فوق توسط کارفرما و تیم فنی (بهویژه در خصوص تبدیل
ةبههوؤبهو).
- تأیید قوانین نرمالسازی فوق توسط کارفرما و تیم فنی (بهویژه در خصوص تبدیل
- فاز ۲ — اضافه کردن ماژول Utility:
- افزودن فایل
backend/utils/text_normalizer.pyشامل تابعnormalize_for_search.
- افزودن فایل
- فاز ۳ — پیادهسازی پایگاه داده:
- اضافه کردن فیلدهای
search_textیاnormalized_textدر مدلهای کلیدی (Hadis،HadisCategory،Transmitter،HadisCorrection،ReferenceBook). - تنظیم پر شدن خودکار در
save(). - اجرای یک Management Command برای نرمالسازی دادههای قبلی.
- اضافه کردن فیلدهای
- فاز ۴ — بهروزرسانی Queryset های جستجو:
- اصلاح متدهای
apply_search_filterدر Viewها تا ورودی کاربر را پیش از جستجو نرمال کند.
- اصلاح متدهای
- فاز ۵ — تست و اعتبارسنجی:
- نوشتن تستهای خودکار (Unit Tests) برای کلمات چالشبرانگیز مثل «أنما»، «إِنَّمَا»، «الرَّحْمٰنِ»، «أبو هريرة»، «مسؤول» و اطمینان از نتیجه مثبت در تمامی حالات.