Munculnya ide
Baru-baru ini saya mengunjungi teman-teman dan kami memilih film, dan saya, sebagai penggemar film yang terbakar (sebenarnya, tidak begitu lurus terbakar), menolak semuanya seperti yang dilihat. Dan mereka mengajukan pertanyaan logis kepada saya, tetapi mengapa Anda tidak melihat sama sekali? Saya mengatakan bahwa saya sedang melakukan pencarian film dan saya menonton setiap film yang telah saya tonton, baik dengan rating atau hanya dengan tanda centang bahwa menonton berlangsung. Dan kemudian sebuah pertanyaan muncul di kepala saya, tetapi berapa banyak waktu yang saya habiskan untuk film? Steam memiliki statistik yang nyaman untuk gim, tetapi tidak untuk film. Jadi saya memutuskan untuk menangani ide ini.
Ada apa dengan implementasinya?
Saya telah mengembangkan di ASP.NET selama beberapa tahun dan terbiasa dengan C #, pada awalnya saya ingin menulis utilitas ini di atasnya, tetapi ada masalah dengan lingkungan yang berat dan, karena saya sedikit terbiasa dengan Python, saya terpaksa melakukannya.
Dan di mana mendapatkan data?
Dan di sini saya dihadapkan dengan masalah pertama. Dengan naif saya berasumsi bahwa pencarian film memiliki API publik resmi dan semacam versi gratis. Tetapi saya tidak menemukan hal seperti itu. Ada kesempatan untuk meminta melalui dukungan teknis, tetapi bahkan di sana mereka memberikan hanya untuk jumlah kesembilan, dan saya menulis ini untuk diri saya sendiri dan tidak mau membayarnya dengan cara apa pun.
Secara alami, saya harus mempertimbangkan pilihan untuk mengurai halaman, dan di situlah saya berhenti.

Setiap orang di profil memiliki daftar film yang ditonton dengan deskripsi kecil yang mencakup durasi gambar. Dengan cara ini saya bisa mendapatkan hanya beberapa halaman (saya punya 762 film dan hanya perlu mendapatkan 17 halaman) dan menghitung waktu yang dihabiskan.
Tidak lebih cepat dikatakan daripada dilakukan.
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
Tapi sudah pada tahap debugging, saya mengalami masalah yang diminta pencarian blok bioskop (sekitar 4 iterasi) dan menganggap mereka mencurigakan. Dan dia benar! Tetapi saya juga menyarankan opsi ini dan pindah ke rencana B.
Rencanakan B - ganti proxy seperti sarung tangan
Mengambil server pertama yang muncul yang menyediakan API untuk mendapatkan proxy ip (saya tidak mengiklankan layanan apa pun, mengambil dua tautan pertama dari Google), mengacaukannya dengan bengkok dan terus menulis kode utama. Dan satu jam kemudian, ketika saya hampir selesai, saya diblokir oleh server yang disediakan API! Saya harus mengubahnya ke yang lain, yang menghasilkan daftar tetap, setiap setengah jam, untuk tugas saya ini sudah cukup. Tetapi jika daftar tiba-tiba berakhir, Anda dapat kembali ke opsi sebelumnya (mereka mengeluarkan 10-24 proksi setiap 24 jam).
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")
Menggabungkan semua ini bersama-sama (pada akhirnya saya akan memberikan tautan ke github dengan versi final), saya mendapatkan hal yang hebat untuk menghitung waktu yang dihabiskan untuk film. Dan dia menerima nomor yang disayangi, tadam: "Anda menyia-nyiakan 84542 menit atau 1409,03 jam atau 58,71 hari."
Sia-sia menghabiskan waktu untuk menghitung sia-sia menghabiskan waktu
Padahal, tidak sia-sia. Tugas itu menarik, meskipun hampir tidak perlu, untuk setidaknya seseorang.
Dan sekarang saya dapat memberi tahu semua orang bahwa selama hampir dua bulan dalam hidup saya, saya menonton film!
Jika seseorang juga tertarik untuk memperoleh statistik "penting" seperti itu untuk diri mereka sendiri, cukup salin id profil Anda dan mulai proyek dengan parameter ini dan jika Anda dapat dengan mudah membuang hasil dalam komentar, saya tertarik pada "penggemar film" atau pemula.
Tautan Kode SumberPS Saya juga akan senang mendengar tips tentang peningkatan kode, karena saya menulis sangat sedikit tentang python dan bahkan tidak sepenuhnya mengerti sintaks.