¿Cuánto tiempo pasaste en películas?

El surgimiento de ideas


Recientemente estuve visitando amigos y elegimos una película, y yo, como fanático de las películas quemadas (de hecho, no tan quemado), rechacé todo lo que se veía. Y me hicieron una pregunta lógica, pero ¿por qué no miraste nada? A lo que dije que estaba llevando a cabo una búsqueda de películas y veo todas las películas que he visto, ya sea por calificación o simplemente por un tic que la visualización tuvo lugar. Y luego surgió una pregunta en mi cabeza, pero ¿cuánto tiempo pasé en películas? Steam tiene estadísticas convenientes para el juego, pero nada para películas. Entonces decidí abordar esta idea.



¿Qué pasa con la implementación?


Llevo varios años desarrollando ASP.NET y estoy acostumbrado a C #, al principio quería escribir esta utilidad en él, pero había un problema con un entorno pesado y, como estoy un poco familiarizado con Python, recurrí a él.

¿Y dónde obtener los datos?


Y aquí me enfrento con el primer problema. Asumí ingenuamente que la búsqueda de películas tiene una API pública oficial y algún tipo de versión gratuita. Pero no encontré nada de eso. Existe la oportunidad de solicitar a través del soporte técnico, pero incluso allí dan solo por la enésima cantidad, y escribí esto para mí y no quería pagarlo.

Naturalmente, tuve que considerar la opción de analizar páginas, y fue allí donde me detuve.

imagen

Todos en el perfil tienen una lista de películas vistas con una pequeña descripción que incluye la duración de la imagen. De esta forma solo puedo obtener unas pocas páginas (tengo 762 películas y fue necesario obtener solo 17 páginas) y calcular el tiempo dedicado.

Apenas dicho que hecho.

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 

Pero ya en la etapa de depuración, me encontré con un problema que la búsqueda de cine bloquea las solicitudes (aproximadamente 4 iteraciones) y las considera sospechosas. ¡Y tiene razón! Pero también sugerí esta opción y pasé al plan B.

Plan B: cambia los poderes como guantes


Después de tomar el primer servidor que proporciona una API para obtener proxy IP (no anuncio ningún servicio, tomé los dos primeros enlaces de Google), lo atornillé torpemente y seguí escribiendo el código principal. ¡Y una hora más tarde, cuando estaba a punto de finalizar, el servidor que proporciona la API me bloqueó! Tuve que cambiarlo a otro, que produce una lista fija, cada media hora, para mi tarea, esto es suficiente. Pero si la lista termina repentinamente, puede volver a la opción anterior (emiten 10-24 proxies cada 24 horas).

 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") 

Combinando todo esto juntos (al final le daré un enlace al github con la versión final), obtuve una gran cosa por contar el tiempo dedicado a las películas. Y recibió el preciado número, tadam: "Perdiste 84542 minutos o 1409.03 horas o 58.71 días".

En vano pasó el tiempo para contar en vano pasó el tiempo


De hecho, no en vano. La tarea era interesante, aunque apenas necesaria, al menos para alguien.
¡Y ahora puedo decirles a todos que durante casi dos meses de mi vida estuve viendo una película!

Si alguien también está interesado en obtener estadísticas "importantes" para sí mismo, simplemente copie la identificación de su perfil y comience el proyecto con este parámetro y si puede descartar fácilmente el resultado en el comentario, estoy interesado en un fanático de la película o un principiante.

Enlace al código fuente

PD: También me complacerá escuchar consejos sobre cómo mejorar el código, ya que escribí muy poco en Python e incluso no entiendo completamente la sintaxis.

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


All Articles