من المحلل اللغوي لملصق مسرح بيثون إلى روبوت Telegram. الجزء 1



أنا حقا أحب الأوبرا والباليه ، ولكن ليس حقا - إعطاء الكثير من المال للتذاكر. كانت المشاهدة اليومية للموقع الإلكتروني للمسرح مع كزة في كل زر مرهقة للغاية ، وكانت التذاكر التي ظهرت فجأة والتي بلغت 170 روبل للقطارات الفائقة مفجعة.
لأتمتة هذا النشاط التجاري ، ظهر برنامج نصي يتم تشغيله على ملصق ويقوم بجمع معلومات حول أرخص التذاكر في الشهر المحدد. طلبات من سلسلة "إصدار قائمة بجميع الأوبرا في مارس على المسرح القديم والجديد يصل إلى 1000 روبل." سقط أحد الأصدقاء "ألا تفعل روبوت Telegram؟" لم يكن هذا في الخطة ، ولكن لماذا لا. ولد الروبوت ، على الرغم من أنه كان يدور على كمبيوتر محمول في المنزل.
ثم تم حظر Telegram. لقد تلاشت فكرة دفع الروبوت إلى الخادم العامل ، كما تلاشى الاهتمام بإظهار الوظيفة. تحت القص ، أتحدث عن مصير مخبر التذاكر الرخيصة من البداية وما حدث له بعد سنة من الاستخدام.

1. أصل الفكرة وبيان المشكلة


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

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

2. التنفيذ الأول. الحد الأدنى من الوظائف


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

من صفحة html ، نحتاج إلى قراءة عناوين URL الخالصة ، ثم الاطلاع عليها ومعرفة علامة السعر. هذه هي الطريقة التي يتم تجميع قائمة الارتباطات.
import requests import numpy as np from bs4 import BeautifulSoup def get_text(url): # URL  html r = requests.get(url) text=r.text return text def get_items(text,top_name,class_name): """   html-  "" url-, ..  - .       top_name  class_name   -  <a class="c_theatre2 c_chamber_halls" href="//tickets.mariinsky.ru/ru/performance/WWpGeDRORFUwUkRjME13/"> </a> """ soup = BeautifulSoup(text, "lxml") film_list = soup.find('div', {'class': top_name}) items = film_list.find_all('div', {'class': [class_name]}) dirty_link=[] for item in items: dirty_link.append(str(item.find('a'))) return dirty_link def get_links(dirty_list,start,end): # ""    URL- links=[] for row in dirty_list: if row!='None': i_beg=row.find(start) i_end=row.rfind(end) if i_beg!=-1 & i_end!=-1: links.append(row[i_beg:i_end]) return links # ,    ,      num=int(input('    : ')) #URL  .      ,    =) url ='https://www.mariinsky.ru/ru/playbill/playbill/?year=2019&month='+str(num) #    top_name='container content gr_top' class_name='t_button' start='tickets' end='/">' #  text=get_text(url) dirty_link=get_items(text,top_name,class_name) #   URL-,     links=get_links(dirty_link,start,end) 

بعد دراسة هيكل الصفحة عند شراء التذاكر ، بالإضافة إلى عتبة السعر ، قررت منح المستخدم الفرصة لاختيار:

  • نوع الأداء (1-opera ، 2-ballet ، 3-concert ، 4-lecture)
  • مكان (مرحلة واحدة ، مرحلة جديدة ، قاعة 3 حفلات ، قاعات مكونة من 4 غرف)

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

بعد ذلك ، نذهب من خلال جميع الروابط الواردة. نحن نصنع get_text ونبحث عن السعر الأقل عليه ، ونقوم أيضًا بسحب المعلومات ذات الصلة. نظرًا لأنه يتعين عليك البحث في كل عنوان URL وتحويله إلى نص ، فإن وقت تشغيل البرنامج ليس فوريًا. سيكون من الرائع تحسين ، لكنني لم أفكر في كيفية القيام بذلك.
لن أذكر الرمز نفسه ، فسيكون طويلًا بعض الشيء ، ولكن كل شيء صحيح هناك بشكل كافٍ و "حدسي" مع Beautiful Soup 4.
إذا كان السعر أقل من السعر المعلن من قبل المستخدم ويتوافق نوع الكتابة مع المجموعة ، فسيتم عرض رسالة حول الأداء في وحدة التحكم. كان هناك خيار آخر لحفظ كل هذا في .xls ، لكنه لم يتجذر. من السهل النظر إلى وحدة التحكم ومتابعة الروابط على الفور بدلاً من البحث في ملف.
صورة

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

3. تمديد وظيفة


في المرحلة الثانية ، قررت تتبع تغييرات الأسعار ، وتخزين الروابط لأداء الفائدة في ملف منفصل (بدقة أكبر ، عنوان URL الخاص بهم). بادئ ذي بدء ، هذا مهم بالنسبة للباليه - نادرًا ما يكون رخيصًا جدًا ولن يقع في قضية الميزانية العامة. ولكن من 5 آلاف إلى 2x ، يكون الانخفاض كبيرًا ، خاصةً إذا كان الأداء رائعًا وأردت تتبعه.
للقيام بذلك ، يجب أولاً إضافة عناوين URL للتتبع ، ثم "التخلص منها" بشكل دوري ومقارنة السعر الجديد بالسعر القديم.
 def add_new_URL(user_id,perf_url): #user_id ,        - WAITING_FILE = "waiting_list.csv" with open(WAITING_FILE, "a", newline="") as file: curent_url='https://'+perf_url text=get_text(curent_url) #      - , ,,   minP, name,date,typ,place=find_lowest(text) user = [str(user_id), perf_url,str(m)] writer = csv.writer(file) writer.writerow(user) def update_prices(): #        print(' ') WAITING_FILE = "waiting_list.csv" with open(WAITING_FILE, "r", newline="") as file: reader = csv.reader(file) gen=[] for row in reader: gen.append(list(row)) L=len(gen) lowest={} with open(WAITING_FILE, "w", newline="") as fl: writer = csv.writer(fl) for i in range(L): lowest[gen[i][1]]=gen[i][2] #   URL  for k in lowest.keys(): text=get_text('https://'+k) minP, name,date,typ,place=find_lowest(text) if minP==0: #     ,      "" minP=100000 if int(minP)<int(lowest[k]): #   ,    lowest[k]=minP for i in range(L): if gen[i][1]==k: #  -  URL   gen[i][2]=str(minP) print('   '+k+'    '+str(minP)) writer.writerows(gen) add_new_URL('12345','tickets.mariinsky.ru/ru/performance/ZVRGZnRNbmd3VERsNU1R/') update_prices() 

تم إطلاق تحديث السعر في بداية البرنامج النصي الرئيسي ، ولم يتم تنفيذه بشكل منفصل. ربما ليست أنيقة كما نود ، لكنها تحل مشكلتها. لذلك كانت الوظيفة الإضافية الثانية هي مراقبة انخفاض الأسعار من أجل أداء الفائدة.

ثم ولد بوت Telegram ، ليس بهذه السهولة ، سريع ، مرح ، ولكن لا يزال ولد. من أجل عدم تجميع كل شيء ، ستكون القصة عنه (وكذلك حول الأفكار غير المحققة ومحاولة القيام بذلك مع موقع مسرح البولشوي) في الجزء الثاني من المقال.

النتيجة: كانت الفكرة ناجحة ، فالمستخدمون راضون. استغرق الأمر بضعة عطلة نهاية أسبوع لمعرفة كيفية التفاعل مع صفحات HTML. لحسن الحظ ، بيثون هي وحدات لغة جاهزة لكل شيء تقريباً ، كما أن الوحدات الجاهزة تساعد على تحريك الظفر دون التفكير في فيزياء المطرقة.

آمل أن تكون القضية مفيدة للحبرشيين ، وربما ستعمل مثل بندلاد سحري لصنع قائمة أمنياتي في رأسي لفترة طويلة.

محدث: استمرار القصة - الجزء 2

Source: https://habr.com/ru/post/ar444460/


All Articles