ظهور الأفكار
كنت في الآونة الأخيرة أقوم بزيارة الأصدقاء واخترنا فيلمًا ، وأنا كمشجع فيلم محترق (في الواقع ، لم يحترق بشكل مباشر) ، رفض كل شيء كما تم مشاهدته. وقد سألوني سؤالًا منطقيًا ، لكن لماذا لم تنظر إليه على الإطلاق؟ قلت له إنني أجري بحثًا عن فيلم وأشاهد كل فيلم شاهدته ، إما بالتصنيف أو بمجرد وضع علامة على العرض. ثم طرح سؤال في رأسي ، ولكن كم من الوقت أمضيت في الأفلام؟ يحتوي Steam على إحصائيات ملائمة للعبة ، ولكن لا يوجد شيء للأفلام. لذلك قررت معالجة هذه الفكرة.
ما الأمر مع التنفيذ؟
لقد تطورت على ASP.NET لعدة سنوات واعتدت على C # ، في البداية كنت أرغب في كتابة هذه الأداة المساعدة عليها ، ولكن كانت هناك مشكلة في بيئة ثقيلة ، ولأنني مألوفة قليلاً مع Python ، فقد لجأت إليها.
وأين تحصل على البيانات؟
وهنا أواجه المشكلة الأولى. لقد افترضت بسذاجة أن البحث عن الأفلام يحتوي على واجهة برمجة تطبيقات عامة رسمية ونوع من الإصدار المجاني. لكني لم أجد أي شيء من هذا القبيل. هناك فرصة لطلب من خلال الدعم الفني ، ولكن حتى هناك يعطون فقط المبلغ التاسع ، وقد كتبت هذا لنفسي ولم أرغب في دفع ثمنه.
بطبيعة الحال ، كان عليّ التفكير في خيار تحليل الصفحات ، وتوقفت عندها.

كل شخص في الملف الشخصي لديه قائمة بالأفلام التي تمت مشاهدتها مع وصف صغير يتضمن مدة الصورة. بهذه الطريقة يمكنني الحصول على بضع صفحات فقط (لدي 762 فيلم وكان من الضروري الحصول على 17 صفحة فقط) وحساب الوقت المستغرق.
لم يقل من فعله.
class KinopoiskParser: def __init__(self, user_id, current_page=1): self._user_id = user_id self._current_page = current_page self._wasted_time_in_minutes = 0 def calculate_wasted_time(self): while True: film_list_url = f'https://www.kinopoisk.ru/user/{self._user_id}' \ f'/votes/list/ord/date/genre/films/page/{self._current_page}/#list' try: film_response = requests.get(film_list_url).text except BaseException: proxy_manager.update_proxy() continue user_page = BeautifulSoup(film_response, "html.parser") is_end = kinopoisk_parser._check_that_is_end_of_film_list(user_page) if is_end: break wasted_time = self._get_film_duration_on_page(user_page) self._wasted_time_in_minutes += wasted_time print(f'Page {self._current_page}, wasted time {self._wasted_time_in_minutes}') self._move_next_page() def get_wasted_time(self): return self._wasted_time_in_minutes def _move_next_page(self): self._current_page += 1 @staticmethod def _get_film_duration_on_page(user_page): try: wasted_time = 0 film_list = user_page.findAll("div", {"class": "profileFilmsList"})[0].findAll("div", {"class": "item"}) for film in film_list: film_description = film.findAll("span") if len(film_description) <= 1: continue film_duration_in_minutes = int(film_description[1].string.split(" ")[0]) wasted_time = wasted_time + film_duration_in_minutes return wasted_time except BaseException: print("Something went wrong.") return 0 @staticmethod def _check_that_is_captcha(html): captcha_element = html.find_all("a", {"href": "//yandex.ru/support/captcha/"}) return len(captcha_element) > 0 @staticmethod def _check_that_is_end_of_film_list(html): error_element = html.find_all("div", {"class": "error-page__container-left"}) return len(error_element) > 0
ولكن بالفعل في مرحلة التصحيح ، واجهت مشكلة أن البحث في السينما يحظر الطلبات (حوالي 4 تكرارات) ويعتبرها مريبة. وهو على حق! ولكني اقترحت أيضًا هذا الخيار وانتقلت إلى الخطة ب.
الخطة ب - تغيير الوكلاء مثل القفازات
باستخدام أول خادم تم إنشاؤه يوفر واجهة برمجة تطبيقات للحصول على وكيل IP (لا أعلن عن أي خدمات ، وأخذت أول رابطين من Google) ، وثبته بشكل خاطئ واستمر في كتابة الرمز الرئيسي. وبعد ساعة ، عندما كنت على وشك الانتهاء ، تم حظري من قبل الخادم الذي توفره واجهة برمجة التطبيقات! اضطررت إلى تغييرها إلى قائمة أخرى ، والتي تنتج قائمة ثابتة ، كل نصف ساعة ، لمهمتي هذا يكفي. ولكن إذا انتهت القائمة فجأة ، يمكنك العودة إلى الخيار السابق (يصدرون 10-24 وكلاء كل 24 ساعة).
class ProxyManager: def __init__(self): self._current_proxy = "" self._current_proxy_index = -1 self._proxy_list = [] self._get_proxy_list() def get_proxies(self): proxies = { "http": self._current_proxy, "https": self._current_proxy } return proxies def update_proxy(self): self._current_proxy_index += 1 if self._current_proxy_index == len(self._proxy_list): print("Proxies are ended") print("Try get alternative proxy") proxy_ip_with_port = self._get_another_proxy() print("Proxy updated to " + proxy_ip_with_port) self._current_proxy = f'http://{proxy_ip_with_port}' return self._current_proxy proxy_ip_with_port = self._proxy_list[self._current_proxy_index] print("Proxy updated to " + proxy_ip_with_port) self._current_proxy = f'http://{proxy_ip_with_port}' return self._current_proxy @staticmethod def _get_another_proxy(): proxy_response = requests.get("https://api.getproxylist.com/proxy?protocol[]=http", headers={ 'Content-Type': 'application/json' }).json() ip = proxy_response['ip'] port = proxy_response['port'] proxy = f'{ip}:{port}' return proxy def _get_proxy_list(self): proxy_response = requests.get("http://www.freeproxy-list.ru/api/proxy?anonymity=false&token=demo") self._proxy_list = proxy_response.text.split("\n")
من خلال الجمع بين كل هذا معًا (في النهاية سأقدم رابطًا إلى github مع الإصدار النهائي) ، حصلت على شيء رائع لحساب الوقت الذي تقضيه في الأفلام. وحصل على الرقم العزيز "تضامن": "أهدرت 84542 دقيقة أو 1409.03 ساعة أو 58.71 يوم".
قضى عبثا الوقت الذي قضيته عبثا قضى الوقت
في الواقع ، ليس عبثا. كانت المهمة مثيرة للاهتمام ، على الرغم من أنها ليست ضرورية ، على الأقل لشخص ما.
والآن أستطيع أن أقول للجميع أنني كنت أشاهد فيلمًا طوال شهرين تقريبًا من حياتي!
إذا كان شخص ما مهتمًا أيضًا بالحصول على هذه الإحصائيات "المهمة" لأنفسه ، فما عليك سوى نسخ معرف ملفك الشخصي وبدء المشروع باستخدام هذه المعلمة وإذا كنت تستطيع تجاهل النتيجة بسهولة في التعليق ، فأنا مهتم بمشجع فيلم أو مبتدئ.
رابط كود المصدرPS سأكون سعيدًا أيضًا لسماع النصائح حول تحسين الرمز ، لأنني كتبت القليل جدًا عن python وحتى أنني لم أفهم تمامًا بناء الجملة.