سكربت بايثون لاستخلاص أسماء منطقية للملفات

سكربت بايثون لاستخلاص أسماء منطقية للملفات من موقع ComicOnlineFree.net
 

توجد عدة مواقع إلكترونية تتيح قراءة الكومكس مجانا، ومنها موقع ComicOnlineFree.net
(و readallcomics , zipcomic , view-comic)
ويمكن بسهولة عرض كل صفحات إحدى القصص المصورة دفعة واحدة، وبالتالي حفظها عن طريق المتصفح للقراءة "أوفلاين" فيما بعد.
لكن ماذا لو لم تكن ترغب في القراءة باستخدام المتصفح، خصوصا وأن للكوميكس برامج مفيدة تعطيك ميزات أكثر لا تتوفر في المتصفحات؟
يمكن أن تفتح مجلد ملفات الصور (الذي يتكون تلقائيا عند تحميل الصفحة عن طريق المتصفح) ثم ترتب هذه الصور وتجمعها في ملف مضغوط بامتداد cbz أو cbr (وهي مجرد إعادة تسمية لملفات zip  و rar الشهيرة)، ثم تستمتع بقراءتها في برنامج استعراض الكوميكس المفضل عندك.

المشكلة هنا في خطوة "ترتيب" الصور. فالموقع - بالاطلاع على مصدر صفحته الـ html بخاصية view source في المتصفح - يسحب الصور من حساب على موقع المدونات الشهير blogspot (التابع لجوجل)، والذي يعطي للملفات أسماء عشوائية غير مرتبة، وبالتالي ستضطر لتعديل أسماء الصور يدويا! وهي عملية مملة.
تأتي البرمجة هنا لإنقاذ الموقف.. فما هي في الحقيقة إلا طريقة لـ "أتمتة" العمليات المملة المكررة.
إن كنت مبتدئا في تعلم لغة البايثون فهذا المثال سيفيدك.

عند النظر لمصدر الصفحة سترى أن كل صورة ترد في فقرة بهذا الشكل:
<img class="lazyload chapter_img" data-original="https://2.bp.blogspot.com/ieHH8iVFg_kqglEW89c6sz9TFnoDga3vfpbxGL3pQYI5zZMMALvrAVZNOaVCYHV5vdtJOWwUMT4RAva5TRERzyuh8eSoLZkdzLsKFLRPwJNhN_LKHj9SXKZqFiUNo-2HrnGCi-NLpw=s1600" src="data:image/png;base64,R0lGODlhAQABAAD/ACwAAAAAAQABAAACADs=" style="margin-bottom: 10px;" alt="The League of Extraordinary Gentlemen Volume 4: The Tempest 6 Page 2" />
ومتصفح فايرفوكس عندما قام بتنزيل هذه الصورة ووضعها في مجلد الصور اختصر اسمها الطويل وجعله هكذا
ieHH8iVFg_kqglEW89c6sz9TFnoDga3vfpbxGL3pQYI5zZMMALvrAVZNOaV.jpeg

ادرس الفقرة واقسمها أجزاء، فستجد أنها تبدأ بـ
<img class
وأن الموقع يسحب الصورة من بلوج-سبوت
وأن الموقع يوفر وسم alt لتخزين "اسم بديل" للصورة، يظهر للقراء عند الوقوف عليه بالفأرة.
وهذه الملاحظة الأخيرة وفرت علينا الجهد وستختصر خطوات حل المشكلة. لأن هذا الاسم البديل يصلح لأن يكون اسما لملف الصورة، وبه رقم مميز سيسهل عملية ترتيب الصور.
إذن كل ما علينا هو استخلاص هذا الوسم من كل فقرة، ثم إعادة تسمية الصورة المرتبطة به (والموجودة في مجلد الصور الذي حفظه المتصفح عندك) بحيث يصبح اسمها الجديد منطقيا، لا عشوائيا كما هو الحال حتى الآن.

كيف سننجز هذه المهمة؟
بالتأكيد سنستخدم regex (للبحث عن الأجزاء النصية المطلوبة)
وسنستخدم loop لتكرار عملية الاستخلاص من كل الفقرات، حتى آخر صورة من صور الكوميكس
وسنستخدم موديول الـ os للتعامل مع الملفات والمجلدات وإعادة تسمية الملفات
وربما نستخدم موديول الـ sys أيضا لتيسير استخدام السكربت من سطر الأوامر، وكي لا يصبح اسم الملف hard-coded في السكربت بل متغيرا مع كل استخدام. (هذه المرونة مفيدة)

الحل سيكون في خطوتين رئيسيتين: أولا نقرأ ملف الـ html النصي، ونستخلص منه اسم كل صورة
ثم نحول اهتمامنا لمجلد الصور، فنعيد تسمية ملفات الصور لأسماء منطقية ومرتبة تصاعديا


import re, os, sys

html = sys.argv[1]
names = {}


بهذه السطور المبدئية قمنا باستيراد الموديولز التي سنحتاجها، وأخذنا من المستخدم اسم ملف الـ html الذي سيجري العمل عليه (وبالتبعية اسم مجلد الصور، لأنه في العادة يكون مكونا من اسم الملف متبوعا باللاحقة _files) وخزناه في متغير اسمه html، ثم أنشأنا قاموسا فارغا كي نجمع فيه بين كل اسم صورة عشوائي وبين اسمها المنطقي المستخلص من الوسم alt
فيما بعد سنستخدم محتويات هذا الـ dictionary في إعادة تسمية ملفات الصور


with open(html + ".html") as f:
    for line in f:
        if re.match(r'<img class=', line):
            m1 = re.search(r'http.+blogspot\.com/(.{1,60})', line)
            m2 = re.search(r'alt="(.+)"', line)
            names[m1.group(1)] = m2.group(1)


في هذه السطور فتحنا ملف الـ html النصي، للقراءة منه سطر سطر، ثم استخدمنا الـ regex (أي لغة الـ regular expressions) للبحث عن السطور التي تبدأ ب <img لأنها السطور التي تعنينا هنا (بالملف عشرات السطور الأخرى التي لا تهمنا)
ثم دخلنا في كل سطر من السطور المهمة، واستخلصنا جزئين (وأحطناهما بأقواس هلالية كي نستدعيهم كمجموعة مستقلة بذاتها): اسم الملف العشوائي القادم من موقع بلوج-سبوت، ووسم الاسم البديل الذي أضافه موقع عرض الكوميكس.
ثم أضفنا كل هذا للقاموس، كل زوجين كـ item مفتاحه key الاسم العشوائي وقيمته value الاسم المنطقي

ملاحظة: رموز البحث في لغة regex غريبة، ويعاني منها جميع المبتدئين (بل وبعض المحترفين)، لكن وثائق البايثون تشرحها باستفاضة وبطريقة واضحة، خصوصا ملحق الـ HowTo الموجود بملف مساعدة لغة البايثون وموقع البايثون الإلكتروني.
لكن باختصار شديد سأشرح الرموز المستخدمة هنا:
الـ r قبل السترينج هنا مهمة، لأنها تغنينا عن عمل escape لكل علامات الباك-سلاش /
النقطة . تحل محل أي حرف
علامة + تعني أن ما قبلها مباشرة يجب أن يوجد في النص محل البحث مرة على الأقل
النقطة الموجودة قبل كلمة com ليس المقصود منها رمز النقطة التي تحل محل أي حرف، ولهذا اضطرننا لسبقها بباكسلاش كي يفهم البايثون أنها مجرد نقطة عادية تستخدم في روابط صفحات الإنترنت
الـ () تستخدم لتحديد جروب معينة، وبالتالي يمكننا الإشارة لها فيما بعد باستخدام الميثود group
الـ {} هي وسيلة أخرى لتحديد مرات تكرار الحرف السابق لها، لكن في حين أن + تعني "مرة واحدة أو أكثر" فإن هذه الأقواس تسمح لك بتحديد حد أدنى وحد أقصى للتكرار. هنا اخترت العدد 60 لأني لاحظت أن متصفح فايرفوكس عندما اختصر اسم ملف الصورة جعله 59 حرفا، وبهذا نضمن أننا استخلصنا قطعة كافية من الاسم العشوائي تضمن لنا وجود اسم ملف الصورة (بمجلد الصور) بها.



for fn in os.listdir(path = "./" + html + "_files"):
    for k in names.keys():
        if k.startswith(fn[:-5]):
            os.rename("./" + html + "_files/" + fn , "./" + html + "_files/" + names[k] + ".jpg")


بهذه السطور يكون البرنامج قد اكتمل. أولا نَدخل مجلد الصور، ثم نعرض قائمة بأسماء الملفات الموجودة به، ثم نقارن بين كل اسم ملف وبين مفاتيح القاموس الذي جمعنا فيه المعلومات المستخلصة من ملف الـ html، فإن وجدنا أن كليهما يبدأ بنفس الحروف العشوائية (مع استبعاد امتداد الملف عند المقارنة، والذي هو هنا .jpeg ، ولهذا قمت بعمل slice لآخر خمس حروف من اسم ملف الصورة) نقوم بإعادة تسمية الملف، وبالطبع سنأخذ الاسم الجديد من قيمة القاموس المقابلة للمفتاح المناسب.


والآن كل ما علينا لتشغيل سكربت إعادة التسمية هذا هو أن نضعه في مجلد خارجي، ونضع جواره ملف الـ html النصي الذي حملناه من موقع الكومكس، وأن نضع جوارهما مجلد الصور الملحق بملف ال html،
ثم نفتح طرفية terminal ونكتب في سطر الأوامر طريقة تشغيل مفسر البايثون ثم اسم ملف السكربت الذي برمجناه ثم اسم ملف الـ html (دون امتداده)
مثال:
> python3 MyScript.py superman_no_1


تعليقات

المشاركات الشائعة من هذه المدونة

100 Arabic words in Frank Herbert's Dune

Darth Vader's Jewish Origin - The Golem of Star Wars

الفلك وفلكة المغزل