تقول مؤلفة المقال ، الذي ننشره اليوم ، إن هدفها هو التحدث عن تطوير مكشطة Python على الويب باستخدام Selenium ، والتي تبحث عن أسعار تذاكر الطيران. عند البحث عن تذاكر ، يتم استخدام التواريخ المرنة (+ - 3 أيام بالنسبة إلى التواريخ المحددة). يحفظ Scraper نتائج البحث في ملف Excel ويرسلها إلى الشخص الذي أطلقها رسالة بريد إلكتروني بها معلومات عامة حول ما تمكن من العثور عليه. الهدف من هذا المشروع هو مساعدة المسافرين في العثور على أفضل الصفقات.

إذا شعرت أنك ، عند التعامل مع المواد ، أنك ضائع - ألقِ نظرة على
هذه المقالة.
ما الذي نبحث عنه؟
أنت حر في استخدام النظام الموضح هنا بالطريقة التي تريدها. على سبيل المثال ، استخدمته للبحث عن رحلات نهاية الأسبوع وتذاكر السفر إلى مسقط رأسي. إذا كنت جادًا في العثور على تذاكر مربحة ، يمكنك تشغيل البرنامج النصي على الخادم (خادم بسيط مقابل 130 روبل شهريًا ، مناسب تمامًا لهذا) وجعله يعمل مرة واحدة أو مرتين يوميًا. سيتم إرسال نتائج البحث إليك. بالإضافة إلى ذلك ، أوصي بتكوين كل شيء بحيث يحفظ البرنامج النصي ملف Excel بنتائج البحث في مجلد Dropbox ، والذي يسمح لك بمشاهدة هذه الملفات من أي مكان وفي أي وقت.
لم أجد تعريفات مع وجود أخطاء حتى الآن ، لكنني أعتقد أن هذا ممكنعند البحث ، كما قيل بالفعل ، يتم استخدام "تاريخ مرن" ، يجد البرنامج النصي العروض التي تقع في غضون ثلاثة أيام من التواريخ المحددة. على الرغم من أنه عند بدء تشغيل البرنامج النصي ، فإنه يبحث عن العروض في اتجاه واحد فقط ، إلا أنه من السهل صقلها بحيث يمكنه جمع البيانات في عدة اتجاهات من الرحلات الجوية. من خلال مساعدتها ، يمكنك البحث عن التعريفات الخاطئة ، مثل هذه الاكتشافات يمكن أن تكون ممتعة للغاية.
لماذا أحتاج إلى مكشطة ويب أخرى؟
عندما بدأت كشط الويب لأول مرة ، لأكون صادقًا ، لم يكن الأمر ممتعًا بشكل خاص. أردت أن أقوم بالمزيد من المشاريع في مجال النمذجة التنبؤية والتحليل المالي ، وربما في مجال تحليل التلوين العاطفي للنصوص. لكن اتضح أنه كان من المثير للاهتمام للغاية - معرفة كيفية إنشاء برنامج يجمع البيانات من المواقع الإلكترونية. عندما بحثت في هذا الموضوع ، أدركت أن كشط الويب هو "محرك" الإنترنت.
قد تقرر أن هذا بيان جريء للغاية. لكن فكر في كيفية بدء Google بمكشطة ويب أنشأتها لاري بيج باستخدام Java و Python. تقوم Googlebots بالبحث واستكشاف الإنترنت ، في محاولة لتزويد مستخدميها بأفضل الإجابات الممكنة على أسئلتهم. يحتوي كشط الويب على عدد لا حصر له من التطبيقات ، وحتى إذا كنت مهتمًا ، في مجال علوم البيانات ، بشيء آخر ، فمن أجل الحصول على بيانات للتحليل ، ستحتاج إلى بعض مهارات الكشط.
بعض الحيل المستخدمة هنا وجدت في
كتاب رائع عن تجريد الويب ، حصلت عليه مؤخرًا. في ذلك يمكنك أن تجد العديد من الأمثلة والأفكار البسيطة حول التطبيق العملي للدراسة. بالإضافة إلى ذلك ، هناك فصل مثير للاهتمام للغاية حول اختبار اختبار reCaptcha. بالنسبة لي ، كان هذا خبرًا ، حيث أنني لم أكن أعرف أن هناك أدوات خاصة وحتى خدمات كاملة لحل مثل هذه المشكلات.
هل تحب السفر؟
بالنسبة للسؤال البسيط وغير المؤذي إلى حد ما الوارد في عنوان هذا القسم ، يمكن للمرء في كثير من الأحيان أن يسمع إجابة إيجابية ، مقدمة مع بضع قصص سفر للشخص الذي سئل إليه. سيتفق معظمنا على أن السفر هو وسيلة رائعة للغطس في بيئات ثقافية جديدة وتوسيع آفاقنا. ومع ذلك ، إذا سألت شخصًا ما سؤالًا حول ما إذا كان يحب البحث عن تذاكر الطيران ، فأنا متأكد من أن الإجابة عليها ستكون بعيدة عن أن تكون إيجابية. في الواقع ، هنا بيثون يأتي لانقاذ.
تتمثل المهمة الأولى التي نحتاج إلى حلها على طريق إنشاء نظام للبحث عن معلومات حول تذاكر الطيران في اختيار منصة مناسبة سنتخذ بها المعلومات. لم يكن حل هذه المشكلة سهلاً بالنسبة لي ، لكن في النهاية اخترت خدمة كاياك. جربت خدمات Momondo و Skyscanner و Expedia وغيرها ، لكن آليات الحماية ضد الروبوتات على هذه الموارد كانت غير قابلة للاختراق. بعد عدة محاولات ، وخلال محاولة إقناع الأنظمة بأنني إنسان ، تعين علي التعامل مع إشارات المرور ومعابر المشاة والدراجات ، قررت أن قوارب الكاياك تناسبني بشكل أفضل ، رغم أنني هنا أيضًا ، إذا تحميل عدد كبير جدًا من الصفحات في وقت قصير ، كما تبدأ الاختبارات أيضًا. تمكنت من جعل الروبوت يرسل طلبات إلى الموقع على فترات من 4 إلى 6 ساعات ، وكل شيء سار على ما يرام. تنشأ الصعوبات أيضًا بشكل دوري عند العمل مع كاياك ، ولكن إذا بدأت إزعاجك بالشيكات ، فأنت بحاجة إلى التعامل معهم يدويًا ، ثم بدء الروبوت ، أو الانتظار بضع ساعات ، ويجب أن تتوقف الشيكات. إذا لزم الأمر ، يمكنك تكييف الكود جيدًا لمنصة أخرى ، وإذا قمت بذلك ، يمكنك الإبلاغ عنه في التعليقات.
إذا كنت بدأت للتو في إلغاء استخدام الويب ، ولا تعرف لماذا تكافح بعض مواقع الويب عليه ، فقبل أن تبدأ مشروعك الأول في هذا المجال ، تفضل بنفسك وابحث عن Google عن الكلمات "آداب تجريف الويب". قد تنتهي تجاربك في وقت أقرب مما تعتقد إذا كنت منخرطًا بشكل غير معقول في عمليات التجريد عبر الويب.
الابتداء
فيما يلي نظرة عامة على ما سيحدث في شفرة مكشطة الويب الخاصة بنا:
- استيراد المكتبات المطلوبة.
- افتح علامة تبويب Google Chrome.
- استدعاء الوظيفة التي تطلق الروبوت ، لتمريره المدينة والتاريخ ، والتي سيتم استخدامها عند البحث عن التذاكر.
- تتلقى هذه الوظيفة نتائج البحث الأولى ، مرتبة وفقًا لمعايير الأكثر جاذبية (الأفضل) ، وتضغط على الزر لتحميل نتائج إضافية.
- تقوم دالة أخرى بجمع البيانات من الصفحة بأكملها وإرجاع إطار بيانات.
- يتم تنفيذ الخطوتين السابقتين باستخدام أنواع الفرز حسب سعر التذكرة (رخيص) وسرعة الطيران (الأسرع).
- يتم إرسال بريد إلكتروني إلى مستخدم البرنامج النصي يتضمن ملخصًا موجزًا لأسعار التذاكر (أرخص التذاكر ومتوسط السعر) ، ويتم حفظ إطار البيانات مع المعلومات التي تم فرزها حسب المؤشرات الثلاثة المذكورة كملف Excel.
- يتم تنفيذ جميع الإجراءات المذكورة أعلاه في دورة بعد فترة زمنية محددة.
تجدر الإشارة إلى أن كل مشروع سيلينيوم يبدأ باستخدام برنامج تشغيل ويب. يمكنني استخدام
Chromedriver ، والعمل مع Google Chrome ، ولكن هناك خيارات أخرى. كما تحظى بشعبية هي PhantomJS و Firefox. بعد تحميل برنامج التشغيل ، تحتاج إلى وضعه في المجلد المناسب ، وهذا يكمل الإعداد لاستخدامه. تفتح الأسطر الأولى من النص البرمجي علامة تبويب جديدة في Chrome.
ضع في اعتبارك أنه ، في قصتي ، لا أحاول فتح آفاق جديدة للعثور على عروض مربحة على تذاكر الطيران. هناك تقنيات أكثر تطوراً لإيجاد مثل هذه العروض. أريد فقط أن أقدم لقراء هذه المواد طريقة بسيطة ولكنها عملية لحل هذه المشكلة.
إليك الكود الذي تحدثنا عنه أعلاه.
from time import sleep, strftime from random import randint import pandas as pd from selenium import webdriver from selenium.webdriver.common.keys import Keys import smtplib from email.mime.multipart import MIMEMultipart
في بداية الكود ، يمكنك رؤية أوامر استيراد الحزمة التي يتم استخدامها خلال مشروعنا. لذلك ، يتم استخدام
randint
بحيث "تغفو الروبوتات" لعدة ثوانٍ عشوائية قبل بدء عملية بحث جديدة. عادة لا يستطيع أي روبوت واحد الاستغناء عنه. إذا قمت بتشغيل الشفرة أعلاه ، سيتم فتح نافذة Chrome ، والتي سيستخدمها الروبوت للعمل مع المواقع.
لنقم بتجربة بسيطة وفتح موقع kayak.com في نافذة منفصلة. اختر المدينة التي سنذهب منها ، والمدينة التي نريد الوصول إليها ، وكذلك تواريخ الرحلات الجوية. عند اختيار التواريخ ، سنتحقق من أن النطاق + -3 أيام. لقد كتبت الرمز مع مراعاة ما ينتج عن الموقع استجابة لمثل هذه الطلبات. على سبيل المثال ، إذا كنت بحاجة إلى البحث عن التذاكر فقط للتواريخ المحددة ، فمن المحتمل جدًا أن تضطر إلى تعديل رمز bot. أتحدث عن الكود ، أقدم تفسيرات مناسبة ، لكن إذا شعرت أنك مشوش - فأعلمني بذلك.
الآن انقر على زر بدء البحث وانظر إلى الرابط في شريط العناوين. يجب أن يبدو وكأنه الرابط الذي أستخدمه في المثال أدناه ، حيث يتم الإعلان عن متغير
kayak
الذي يخزن عنوان URL ، ويتم استخدام طريقة
get
على برنامج تشغيل الويب. بعد النقر على زر البحث ، يجب أن تظهر النتائج على الصفحة.
عندما استخدمت أمر
get
أكثر من مرتين إلى ثلاث مرات في بضع دقائق ، طُلب مني اجتياز اختبار باستخدام reCaptcha. يمكنك متابعة هذا الفحص يدويًا ومتابعة التجارب حتى يقرر النظام ترتيب فحص جديد. عندما اختبرت البرنامج النصي ، شعرت أن جلسة البحث الأولى غائبة دائمًا دون مشاكل ، لذلك إذا كنت ترغب في تجربة الشفرة ، فيجب عليك فقط فحصها يدويًا بشكل دوري وترك الرمز ليتم تنفيذه باستخدام فترات زمنية طويلة بين جلسات البحث. نعم ، وإذا فكرت في ذلك ، فمن غير المرجح أن يحتاج الشخص إلى معلومات حول أسعار التذاكر التي يتم استلامها على فترات زمنية مدتها 10 دقائق بين عمليات البحث.
العمل مع صفحة باستخدام XPath
لذلك ، فتحنا النافذة وقمنا بتحميل الموقع. للحصول على معلومات التسعير وغيرها ، نحتاج إلى استخدام تقنية XPath أو محددات CSS. قررت أن أتطرق إلى XPath ولم أشعر بالحاجة إلى استخدام محددات CSS ، لكن من الممكن تمامًا العمل على هذا النحو. يمكن أن يكون التنقل في صفحة باستخدام XPath مهمة شاقة ، وحتى إذا كنت تستخدم الطرق التي وصفتها في
هذه المقالة ، والتي استخدمت نسخ المعرفات المقابلة من رمز الصفحة ، فقد أدركت أن هذا ، في الواقع ، ليس أفضل طريقة للوصول العناصر الضرورية. بالمناسبة ، في
هذا الكتاب ، يمكنك العثور على وصف ممتاز لأساسيات العمل مع الصفحات التي تستخدم محددات XPath و CSS. إليك ما يبدو عليه أسلوب برنامج تشغيل الويب المقابل.
لذلك ، نحن نواصل العمل على الروبوت. استفد من البرنامج لاختيار أرخص التذاكر. في الصورة التالية ، يتم تمييز رمز محدد XPath باللون الأحمر. لعرض الرمز ، تحتاج إلى النقر بزر الماوس الأيمن فوق عنصر الصفحة التي تهتم بها وتحديد أمر الفحص في القائمة التي تظهر. يمكن استدعاء هذا الأمر لعناصر صفحة مختلفة ، سيتم عرض الرمز الخاص به وتسليط الضوء عليه في نافذة عرض الشفرة.
عرض رمز الصفحةمن أجل العثور على تأكيد منطقي حول عيوب نسخ محددات من التعليمات البرمجية ، انتبه إلى الميزات التالية.
إليك ما تحصل عليه عند نسخ الرمز:
//*[@id="wtKI-price_aTab"]/div[1]/div/div/div[1]/div/span/span
من أجل نسخ شيء مشابه ، تحتاج إلى النقر بزر الماوس الأيمن فوق جزء الكود الذي يثير اهتمامك وتحديد Copy> Copy XPath من القائمة التي تظهر.
هذا ما استخدمته لتحديد الزر "أرخص":
cheap_results = '//a[@data-code = "price"]'
نسخ> نسخ XPath Commandمن الواضح أن الخيار الثاني يبدو أكثر بساطة. عند استخدامه ، يبحث عن العنصر a ، الذي له سمة
data-code
تساوي
price
. عند استخدام الخيار الأول ، يتم البحث عن عنصر
id
والذي هو
wtKI-price_aTab
، بينما يشبه مسار XPath إلى العنصر
/div[1]/div/div/div[1]/div/span/span
. سيقوم طلب XPath مماثل لصفحة بالقيام بالخدعة ، ولكن مرة واحدة فقط. أستطيع أن أقول الآن أن
id
سيتغير في المرة التالية التي يتم فيها تحميل الصفحة.
wtKI
أحرف
wtKI
ديناميكيًا في كل مرة يتم فيها تحميل الصفحة ، ونتيجة لذلك ، فإن الكود الذي يتم استخدامه سيكون عديم الفائدة بعد إعادة تحميل الصفحة التالية. حتى تأخذ بعض الوقت لمعرفة XPath. هذه المعرفة سوف تخدم لك جيدا.
ومع ذلك ، تجدر الإشارة إلى أن نسخ محددات XPath يمكن أن تكون مفيدة عند العمل مع مواقع بسيطة إلى حد ما ، وإذا كان هذا يناسبك ، فلا حرج في ذلك.
الآن دعونا نفكر في ما يجب القيام به إذا كنت بحاجة إلى الحصول على جميع نتائج البحث في عدة أسطر ، داخل القائمة. بسيط جدا كل نتيجة موجودة داخل كائن مع فئة
resultWrapper
. يمكن أن يتم تنزيل جميع النتائج في حلقة تشبه تلك الموضحة أدناه.
تجدر الإشارة إلى أنه إذا فهمت ما سبق ، فعليك بسهولة فهم معظم الشفرة التي سنقوم بتحليلها. في سياق عمل هذا الرمز ، ننتقل إلى ما نحتاج إليه (في الواقع ، هذا هو العنصر الذي يتم فيه التفاف النتيجة) باستخدام بعض الآلية للإشارة إلى المسار (XPath). يتم ذلك من أجل الحصول على نص العنصر ووضعه في كائن يمكن من خلاله قراءة البيانات (استخدم أول
flight_containers
، ثم
flights_list
).
يتم عرض الأسطر الثلاثة الأولى ويمكننا أن نرى بوضوح كل ما نحتاج إليه. ومع ذلك ، لدينا طرق أكثر إثارة للاهتمام للحصول على المعلومات. نحن بحاجة إلى أخذ البيانات من كل عنصر على حدة.
للعمل!
من الأسهل لكتابة وظيفة لتحميل نتائج إضافية ، لذلك دعونا نبدأ بها. أرغب في زيادة عدد الرحلات الجوية التي يتلقاها البرنامج إلى الحد الأقصى ، وفي نفس الوقت لا تسبب الشكوك في الخدمة التي تؤدي إلى التحقق ، لذلك انقر فوق الزر "تحميل المزيد من النتائج" مرة واحدة في كل مرة يتم فيها عرض الصفحة. في هذا الرمز ، يجب الانتباه إلى كتلة
try
، التي أضفتها بسبب حقيقة أنه في بعض الأحيان لا يتم تحميل الزر بشكل طبيعي. إذا واجهت هذا أيضًا ،
start_kayak
بتعليق المكالمات لهذه الوظيفة في رمز وظيفة
start_kayak
، والتي سنناقشها أدناه.
الآن ، بعد إجراء تحليل طويل لهذه الوظيفة (أحيانًا ما يمكنني القيام بها) ، نحن على استعداد لإعلان وظيفة تتعامل مع تجريد الصفحات.
لقد قمت بالفعل بجمع معظم ما هو مطلوب في الوظيفة التالية المسماة
page_scrape
. في بعض الأحيان ، يتم تجميع البيانات التي يتم إرجاعها حول مراحل المسار ، لفصلها يمكنني استخدام طريقة بسيطة. على سبيل المثال ، في المرة الأولى التي أستخدم فيها المتغيرات
section_a_list
و
section_b_list
. تقوم
flights_df
بإرجاع إطار البيانات
flights_df
، مما يسمح لنا بفصل النتائج التي تم الحصول عليها باستخدام طرق مختلفة لفرز البيانات ، ثم دمجها فيما بعد.
def page_scrape(): """This function takes care of the scraping part""" xp_sections = '//*[@class="section duration"]' sections = driver.find_elements_by_xpath(xp_sections) sections_list = [value.text for value in sections] section_a_list = sections_list[::2]
حاولت تسمية المتغيرات بحيث تكون الشفرة واضحة. تذكر أن المتغيرات التي تبدأ بـ تشير إلى الخطوة الأولى من المسار ، و
b
إلى الثانية. انتقل إلى الوظيفة التالية.
الآليات المساعدة
الآن لدينا وظيفة تسمح لك بتحميل نتائج بحث إضافية ووظيفة لمعالجة هذه النتائج. يمكن إكمال هذه المقالة حول هذا الموضوع ، لأن هاتين الوظيفتين توفران كل ما هو ضروري لتجريد الصفحات التي يمكن فتحها بشكل مستقل. لكننا لم ننظر بعد في بعض الآليات المساعدة التي نوقشت أعلاه. على سبيل المثال ، هذا رمز لإرسال رسائل البريد الإلكتروني وبعض الأشياء الأخرى. كل هذا يمكن العثور عليه في وظيفة
start_kayak
، والتي نعتبرها الآن.
لاستخدام هذه الوظيفة ، تحتاج إلى معلومات حول المدن والتواريخ. باستخدام هذه المعلومات ، تقوم بتكوين رابط في متغير
kayak
، والذي يُستخدم للانتقال إلى صفحة تحتوي على نتائج بحث مرتبة حسب أفضل تطابق لها. بعد أول جلسة تجريف ، سوف نعمل مع الأسعار في الجدول في أعلى الصفحة. وهي نجد الحد الأدنى لسعر التذكرة ومتوسط السعر. سيتم إرسال كل هذا ، بالإضافة إلى التنبؤ الصادر عن الموقع ، عبر البريد الإلكتروني. على الصفحة ، يجب أن يكون الجدول المقابل في الزاوية اليسرى العليا. بالمناسبة ، قد يتسبب العمل مع هذا الجدول في حدوث خطأ عند البحث باستخدام التواريخ الدقيقة ، حيث إنه في هذه الحالة لا يتم عرض الجدول على الصفحة.
def start_kayak(city_from, city_to, date_start, date_end): """City codes - it's the IATA codes! Date format - YYYY-MM-DD""" kayak = ('https://www.kayak.com/flights/' + city_from + '-' + city_to + '/' + date_start + '-flexible/' + date_end + '-flexible?sort=bestflight_a') driver.get(kayak) sleep(randint(8,10))
لقد اختبرت هذا البرنامج النصي باستخدام حساب Outlook (hotmail.com). لم أقم بالتحقق من التشغيل الصحيح لحساب Gmail ، نظام البريد هذا شائع جدًا ، ولكن هناك الكثير من الخيارات الممكنة. إذا كنت تستخدم حساب Hotmail ، فلكي تعمل كل شيء ، تحتاج فقط إلى إدخال بياناتك في الكود.
إذا كنت ترغب في فهم ما يتم تنفيذه بالضبط في أقسام منفصلة من رمز هذه الوظيفة ، يمكنك نسخها وتجربتها. تجارب الكود هي الطريقة الوحيدة لفهمها.
نظام جاهز
الآن بعد أن تم كل شيء تحدثنا عنه ، يمكننا إنشاء حلقة بسيطة تسمى وظائفنا. يطلب البرنامج النصي من المستخدم بيانات عن المدن والتواريخ. عند الاختبار من خلال إعادة تشغيل البرنامج النصي بشكل مستمر ، من غير المحتمل أن ترغب في إدخال هذه البيانات في كل مرة يدويًا ، وبالتالي يمكن تعليق الأسطر المقابلة لوقت الاختبار عن طريق إلغاء تثبيت تلك التي تندرج تحتها والتي تكون فيها البيانات اللازمة للبرنامج النصي مشفرة.
city_from = input('From which city? ') city_to = input('Where to? ') date_start = input('Search around which departure date? Please use YYYY-MM-DD format only ') date_end = input('Return when? Please use YYYY-MM-DD format only ')
هنا هو تشغيل اختبار البرنامج النصي.
اختبار تشغيل البرنامج النصيالنتائج
إذا وصلت إلى هذه النقطة - مبروك! الآن لديك مكشطة ويب تعمل ، على الرغم من أنني أرى بالفعل العديد من الطرق لتحسينها. على سبيل المثال ، يمكن دمجها مع Twilio بحيث ترسل رسائل نصية بدلاً من رسائل البريد الإلكتروني. يمكنك استخدام VPN أو أي شيء آخر لتلقي النتائج في وقت واحد من خوادم متعددة. هناك أيضًا مشكلة متكررة في التحقق من مستخدم الموقع لمعرفة ما إذا كان شخصًا ، ولكن يمكن أيضًا حل هذه المشكلة. في أي حال ، الآن لديك قاعدة يمكنك توسيعها إذا كنت ترغب في ذلك. على سبيل المثال ، للتأكد من إرسال ملف Excel إلى المستخدم كمرفق برسالة بريد إلكتروني.
