سؤال

أود اكتشاف ترميز بعض النص (باستخدام PHP). لهذا الغرض ، أستخدم وظيفة mb_detect_encoding ().

المشكلة هي أن الوظيفة تعيد نتائج مختلفة إذا قمت بتغيير ترتيب الترميزات المحتملة باستخدام وظيفة mb_detect_order ().

النظر في المثال التالي

$html = <<< STR
ちょっとのアクセスで落ちてしまったり、サーバー障害が多いレンタルサーバーを選ぶとあなたのビジネス等にかなりの影響がでてしまう可能性があります。特に商売をされている個人の方、法人の方は気をつけるようにしてください
STR;
mb_detect_order(array('UTF-8','EUC-JP', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ISO-2022-JP','ISO-8859-1','ISO-8859-2'));
$originalEncoding = mb_detect_encoding($str);
die($originalEncoding); // $originalEncoding = 'UTF-8'

ومع ذلك ، إذا قمت بتغيير ترتيب الترميزات في mb_detect_order () ستكون النتائج مختلفة:

mb_detect_order(array('EUC-JP','UTF-8', 'SJIS', 'eucJP-win', 'SJIS-win', 'JIS', 'ISO-2022-JP','ISO-8859-1','ISO-8859-2'));        
die($originalEncoding); // $originalEncoding = 'EUC-JP'



لذلك أسئلتي هي:
لماذا يحدث ذلك؟
هل هناك طريقة في PHP إلى اكتشاف ترميز النص بشكل صحيح وبشكل لا لبس فيه؟

هل كانت مفيدة؟

المحلول

هذا ما أتوقع أن يحدث.

ربما تستمر خوارزمية الكشف في المحاولة ، بالترتيب ، الترميزات التي حددتها فيها mb_detect_order ثم إرجاع أول واحد الذي بموجبه سيكون bytestream صالحا.

شيء أكثر ذكاء يتطلب أساليب إحصائية (أعتقد أن التعلم الآلي شائع الاستخدام).

تحرير: انظر على سبيل المثال هذه المقالة لأساليب أكثر ذكاء.

نظرًا لأهميتها ، يتم بالفعل تنفيذ اكتشاف Charset التلقائي في تطبيقات الإنترنت الرئيسية مثل Mozilla أو Internet Explorer. إنها دقيقة وسريعة للغاية ، لكن التنفيذ يطبق العديد من المعرفة المحددة للمجال على أساس كل حالة على حدة. على عكس أساليبهم ، كنا نهدف إلى خوارزمية بسيطة يمكن تطبيقها بشكل موحد على كل Charset ، وتستند الخوارزمية إلى تقنيات التعلم الآلي القياسي الراسخة. لقد درسنا أيضًا العلاقة بين اللغة والكشف عن Charset ، وقارنا الخوارزميات القائمة على البايت والخوارزميات القائمة على الشخصيات. استخدمنا ساذج بايز (NB) ودعم آلة ناقلات (SVM).

نصائح أخرى

ليس صحيحا. غالبًا ما تحتوي الترميزات المختلفة على مساحات واسعة من التداخل ، وإذا كانت السلسلة التي تختبرها موجودة داخل هذا التداخل ، فسيكون كل من الترميز مقبولًا.

على سبيل المثال ، UTF-8 و ISO-8859-1 هي نفسها بالنسبة للأحرف AZ. سيكون للسلسلة "Hello" تسلسل متطابق من البايتات في كلا الترميزين.

هذا هو بالضبط سبب وجود mb_detect_order() الوظيفة في المقام الأول ، لأنها تتيح لك أن تقول ما تفضل حدوثه عندما تحدث هذه الاشتباكات. هل ترغب في أن تكون "مرحبًا" UTF-8 أو ISO-8859-1؟

تذكر mb_detect_encoding() لا يعرف ما هو ترميز البيانات. قد ترى سلسلة ، لكن الوظيفة نفسها ترى فقط دفقًا من البايتات. عند ذلك ، يحتاج إلى تخمين ماهية الترميز-على سبيل المثال ، سيكون ASCII إذا كانت البايتات فقط في نطاق 0-127 ، فستكون UTF-8 إذا كانت هناك بايت ASCII و 128 بايت موجودة فقط في أزواج أو أكثر ، وهكذا دواليك.

كما يمكنك أن تتخيل ، بالنظر إلى هذا السياق ، من الصعب للغاية اكتشاف ترميز بشكل موثوق.

يحب ريك قال ، هذا ما mb_detect_order() الوظيفة هي - أنت تقوم بشكل أساسي بتزويد أفضل ما يمكن أن تكون عليه البيانات. هل تعمل مع ملفات UTF-8 بشكل متكرر؟ ثم من المحتمل أن تكون أغراضك UTF-16 حتى لو mb_detect_encoding() يمكن أن يخمن ذلك.

قد ترغب أيضًا في التحقق Artefactoحلقة الوصل للحصول على عرض أكثر تعمقا.

مثال على ذلك: متصفح الانترنت يستخدم بعض التخمين الترميز المثير للاهتمام إذا لم يتم تحديد شيء (Link ، القسم: "للكشف تلقائيًا من لغة موقع الويب") الذي تسبب في سلوكيات غريبة على مواقع الويب التي أخذت الترميز كأمر مسلم به في الماضي. ربما يمكنك العثور على بعض الأشياء المسلية على ذلك إذا كنت جوجل. إنه يجعل حالة عرض لطيفة كيف يمكن حتى أن تؤدي الأساليب الإحصائية إلى نتائج عكسية بشكل فظيع ، ولماذا يكون تخمين الترميز بشكل عام مشكلة.

MB_DETECT_ENCODING ينظر إلى إدخال Charset الأول في MB_DETECT_ORDER () ثم حلقات من خلال حرف مطابقة $ HTML الخاص بك بحرف ما إذا كان هذا الحرف يقع داخل المجموعة الصالحة من الأحرف لـ Charset. إذا كان كل حرف يتطابق ، فإنه يعود صحيحًا ؛ في حالة فشل أي حرف ، ينتقل إلى Charset التالي في MB_Detect_order () ويحاول مرة أخرى.

قائمة ويكيبيديا من charsets هو مكان جيد لرؤية الشخصيات التي تشكل كل شارت.

نظرًا لأن قيم charset هذه تتداخل (يوجد char x8fa1ef في كل من "UTF-8" وفي "EUC-JP") ، سيعتبر هذا مطابقة على الرغم من أنها شخصية مختلفة تمامًا في كل مجموعة أحرف. لذلك ما لم تكن أي من قيم الأحرف موجودة في charset ، ولكن ليس في آخر ، فإن MB_DETECT_ENCODING لا يمكن تحديد أي من charsets غير صالح ؛ وسوف يعيد أول Charset من قائمة الصفيف الخاصة بك والتي يمكن أن تكون صالحة.

بقدر ما أدرك ، لا توجد طريقة مؤكدة لتحديد Charset. يمكن مساعدة طريقة "أفضل تخمين" لـ PHP إذا كانت لديك فكرة معقولة عن ما هي التي من المحتمل أن تواجهها ، وطلب قائمتك وفقًا لذلك على الفجوات (الأحرف غير صالحة) في كل Charset. أفضل حل هو "معرفة" Charset. إذا كنت تقوم بتجميع HTML الخاص بك من صفحة أخرى ، فابحث عن معرف Charset في رأس تلك الصفحة.

إذا كنت تريد حقًا أن تكون ذكيًا ، فيمكنك محاولة تحديد اللغة التي يتم فيها كتابة HTML ، ربما باستخدام Trigrams أو N-Grams أو ما شابه ذلك كما هو موضح في هذه المقالة على PHP/IR.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top