Я большой поклонник аниме и как любой любовник аниме, я всегда хочу, чтобы быть в курсе моего любимого аниме. Я хочу знать, был ли новым эпизодом и, как правило, я всегда проверяю эти аниме сайты для обновлений. Но что часто происходит, это то, что я в конечном итоге приклеиваю к сайту, обнаружив все больше и больше аниме, пока не поймешь «О, это было три часа!» 😅
Я решил создать приложение, которое просто поддерживает меня с несколькими аниме, которые я хочу посмотреть. Это был довольно хороший способ встать на скорость с помощью веб-соскоба и работать с некоторыми из тех Кивимд компоненты.
Приложение довольно просто. Сначала добавьте URL аниме на https://gogoanime.vc Затем перейдите к экрану «Обновление Anime» и освежитесь, удаваясь. Это начнет процесс соскабливания данных с сайта и отобразит список аниме, с изображением справа от каждого списка элемента и данные о аниме, таком как имя, количество эпизодов, и, закончил ли он нет.
Настройка
Сначала создайте виртуальную среду. Внутри этого установите kivy, kivymd, beautifulsoup4, lxml и запросы со следующими командами:
Пип устанавливает Кив
Пип Установите Кивимд
PIP Установите BS4
PIP Установка запросов
PIP Установите LXML
Мы собираемся использовать lxml
Парсер с bowioSoup4.
Теперь создайте 3 файла в одном каталоге:
main.py
– Содержать основной код приложенияMain.kv
– Содержать код интерфейсаScrap.py
– Этот файл будет содержать весь код, ответственный за соскреб.
Давайте получим кодирование!
Внутри main.py добавьте следующие строки
from kivymd.app import MDApp from kivy.uix.screenmanager import ScreenManager from kivymd.uix.screen import MDScreen class ScreenManagement(ScreenManager): pass class MainWindow(MDScreen): pass class AddUrlScreen(MDScreen): pass class MainApp(MDApp): def build(self): self.theme_cls.primary_palette = "DeepPurple" if __name__ == "__main__": app = MainApp() app.run()
Здесь я просто создаю скелет приложения. Он будет иметь два экрана, основной экран, ответственный за отображение информации аниме и экран URL, где мы можем добавить URL для аниме, который мы хотим лома. Мне нравится цвет фиолетовый И так я установил self.theme_cls.primary_palette
«глубокому». Вы можете проверить kivymd Документация Больше подробностей.
Далее, внутри Main.kv, добавьте следующий код:
ScreenManagement: MainWindow: AddUrlScreen:: name: 'mainscreen' #toolbar MDBoxLayout: orientation: 'vertical' MDToolbar: pos_hint: {'top': 1} title: 'AnimeUpdate' right_action_items: [["link-variant-plus", lambda x: lambda x:app.open_settings_screen()]] MDLabel:
Здесь мы добавляем два экрана, которые мы создали в менеджер экрана. Затем мы определяем экран «MainWindow». Затем мы даем ему имя, чтобы мы могли ссылаться на него позже. Затем мы добавляем панель инструментов с виджетом справа. Виджет позвонит app.open_settings_screen ()
Функция, которую мы создадим позже. «MDLabel» – это просто заполнитель. Если вы запустите приложение, теперь вы получите следующее:
Далее мы добавляем компоновку обновления. Изменить
класс в Main.kv
смотреть следующим образом:
: name: 'mainscreen' #toolbar MDBoxLayout: orientation: 'vertical' MDToolbar: pos_hint: {'top': 1} title: 'AnimeUpdate' right_action_items: [["link-variant-plus", lambda x: lambda x:app.open_settings_screen()]] # add these lines MDScrollViewRefreshLayout: id: refresh_layout refresh_callback: root.refresh_callback root_layout: root MDGridLayout: id: box adaptive_height: True cols: 1
В приведенном выше коде мы добавляем Mdscrollviewlayout
Что собирается позволить нам обновить экран, провожу вниз сверху. Обратите внимание, что мы удалили MDLabel
Отказ Мы также добавляем Mdgridlayout
который собирается содержать элементы списка.
Теперь измените MainWindow
класс в main.py
смотреть следующим образом:
class MainWindow(MDScreen): def refresh_callback(self, *args): print("Refreshing...")
Мы определяем функцию под названием Refresh_Callback
который будет называться, когда мы проводим. На данный момент он собирается распечатать «освежающую …» в терминале.
Сохранить и запустить приложение с Python Main.py
В терминале, а затем проведите на экране:
Далее мы собираемся создать экран URL. Внутри Main.kv
Добавьте следующий код:
: name: 'addurl' id: addurl # toolbar MDBoxLayout: orientation: 'vertical' MDToolbar: pos_hint: {'top': 1} title: 'Settings' left_action_items: [["keyboard-backspace", lambda x: app.return_to_main_window()]] MDFloatLayout: size_hint: 1, .9 id: linkscreen MDTextField: id: linkinput size_hint: .8, None pos_hint: {'center_x': .5, 'y': .9} hint_text: 'Add Url' mode: 'rectangle' text_validate_unfocus: False on_text_validate: root.add_url(linkinput.text) ScrollView: md_bg_color: app.theme_cls.primary_color pos_hint: {'center_x': .5, 'y': .1} size_hint: .9, .8 MDList: id: linklist
AddUrlscreen
Имеет панель инструментов, но на этот раз виджет слева. Этот виджет вернет нас на главный экран, позвонив на app.return_to_main_window ()
Функция, которую мы собираемся определить дальше. Экран URL имеет текстовое поле. Мы набор text_validate_unfocus
к Ложь
Так что текстовое поле не теряет фокусировки, когда мы нажимаем ввод. Когда мы нажимаем ввод, текст внутри текстового поля будет подан на функцию root.add_url ()
Что мы также собираемся определить дальше.
Модифицировать main.py
следующее:
#... from kivy.uix.screenmanager import ScreenManager, CardTransition # new import #... class AddUrlScreen(MDScreen): def add_url(self, text): """Add the url to list and save the url in shelve file""" self.ids.linkinput.focus = True self.ids.linkinput.text = '' print(text) class MainApp(MDApp): def build(self): self.theme_cls.primary_palette = "DeepPurple" self.root.transition= CardTransition() # new line #define methods to switch between screens def open_settings_screen(self): """open setting window""" self.root.current = 'addurl' self.root.transition.direction = 'down' # new method def return_to_main_window(self): self.root.current = 'mainscreen' self.root.transition.direction = 'up'
Здесь мы импортируем Кардтрансция
который является одним из многочисленных анимаций экрана перехода. В AddUrlscreen
Класс, мы также добавляем add_url
Метод, который прямо сейчас отображает только текст в терминале. В MainApp
Класс, мы устанавливаем экран перехода на Кардтрансция
и добавить методы для переключения между Windows.
Теперь мы собираемся определить элемент пользовательского списка, который добавляется в экран URL-адреса всякий раз, когда мы нажимаем Enter в поле Text:
В Main.kv
Добавить:
: IconLeftWidget: icon: "web" IconRightWidget: icon: "trash-can" theme_text_color: "Custom" text_color: 1, 0, 0, 1 on_release: root.delete_item(root.text)
Модифицировать main.py
:
from kivymd.uix.list import OneLineAvatarIconListItem, ThreeLineAvatarIconListItem, ImageLeftWidget # new class class CustomListItem(OneLineAvatarIconListItem): def delete_item(self, text): """Delete list item""" self.parent.remove_widget(self) # modify AddUrlScreen class AddUrlScreen(MDScreen): def add_url(self, text): """Add the url to list""" self.ids.linklist.add_widget(CustomListItem(text=text)) # new line self.ids.linkinput.focus = True self.ids.linkinput.text = '' # removed print line
Мы импортировали три предмета, некоторые из которых мы собираемся использовать позже. Создать CustomListitem
класс, который наследует от Onelineavatariconlistitem
класс. CustomListitem
Иконка слева и значок удаления справа. Если вы запускаете приложение сейчас, вы можете добавлять и удалять элементы:
Теперь мы собираемся настроить способ сохранить URL-адреса, которые мы добавили, чтобы нам не нужно продолжать добавлять URL-адреса каждый раз, когда мы хотим получить информацию о аниме. Для этого мы собираемся использовать Python полза
модуль. Модифицировать main.py
следующее:
import shelve, os # import shelve and os # modify CustomListItem to delete item from shelve file class CustomListItem(OneLineAvatarIconListItem): def delete_item(self, text): """Delete list item""" with shelve.open('./save_files/mydata')as shelf_file: url_list = shelf_file['url_list'] url_list.remove(str(text)) shelf_file['url_list'] = url_list self.parent.remove_widget(self) # modify the AddUrlScreen class class AddUrlScreen(MDScreen): def add_url(self, text): """Add the url to list and save the url in shelve file""" self.ids.linklist.add_widget(CustomListItem(text=text)) self.ids.linkinput.focus = True self.ids.linkinput.text = '' # saving to shelve file with shelve.open('./save_files/mydata') as shelf_file: url_list = shelf_file['url_list'] url_list.append(str(text)) shelf_file['url_list'] = url_list def on_pre_enter(self): '''Load the shelve file with list item from shelve file''' try: with shelve.open('./save_files/mydata') as shelf_file: self.ids.linklist.clear_widgets() for item in shelf_file['url_list']: self.ids.linklist.add_widget(CustomListItem(text=item)) except KeyError: with shelve.open('./save_files/mydata') as shelf_file: shelf_file['url_list'] = [] class MainApp(MDApp): #..... # add this function to create two directories at start up def on_start(self): try: os.mkdir('images') os.mkdir('save_files') except: pass
Хорошо, я знаю, что это много кода Но позвольте мне сделать все возможное, чтобы объяснить, что здесь происходит. Мы изменим CustomListItem, чтобы, когда мы удаляем этот виджет, мы также удаляем данные, которые мы сохранили в файле SLEDLES. В AddUrlscreen
, мы добавляем код, чтобы сохранить данные в полке файла в списке под названием URL_LIST
Отказ Поэтому каждый раз, когда мы нажимаем Enter в текстовом поле, текст сохраняется в файл SLALVE внутри папки с именем Save_files
который находится в нашем текущем рабочем каталоге. On_Pre_enter
Метод позволяет делать вещи, когда мы навигация на AddUrlscreen
. Он загрузит сохраненные URL-адреса и добавить CustomListitem
виджеты. on_start
Функция создает две папки, когда приложение запускается.
Веб соскоб с красивойSUP4
Я не буду входить в детали BeautifulSoup4. Вы можете найти больше информации об этом в Документация Отказ Сайт, который мы собираемся откинуть Gogoanime . Если вы посетите этот сайт, введите имя аниме в поле поиска, и нажмите Enter, вы будете перенаправлены на страницу результатов. Здесь, если вы нажмете на аниме, вы будете направлены на страницу с деталями этого аниме. URL будет выглядеть так: https://gogoanime.vc/category/name-of-anime Отказ
Это тип URL, который будет использоваться ваше приложение для получения деталей. Щелкните правой кнопкой мыши на сайте и нажмите «Осмотреть». Это откроет небольшой раздел, который позволяет просматривать детали определенных элементов, таких как HTML, используемый для их создания и их классов и так далее. Мы собираемся выбрать изображение, имя аниме, статус и количество эпизодов. Есть много способов выбрать элементы, используя PositionSoup4, я использовал селекторы CSS.
Внутри Scrap.py
Добавьте следующий код:
import os,sys import requests import shelve from bs4 import BeautifulSoup def download_webpage(url): try: # use requests to get the url text res = requests.get(url) res.raise_for_status() # parse the text to BeautifulSoup get_soup_text = BeautifulSoup(res.text, features='lxml') # download the image print("Downloading") download_details(get_soup_text) except Exception as e: print(e) def download_details(soup_text): # get the anime title anime_title = soup_text.select('.anime_info_episodes > h2')[0].getText() # get the number of episodes episodes = soup_text.select('.anime_video_body ul li .active')[0].get('ep_end') # get the status completed = True if soup_text.find(title = 'Completed Anime') != None else False ongoing = True if soup_text.find(title = 'Ongoing Anime') != None else False # get the image image_elements = soup_text.select('.anime_info_body_bg img') if image_elements == []: pass else: # get image source image_url = image_elements[0].get('src') image = requests.get(image_url) image.raise_for_status() ## Save details to shelve file with shelve.open('./save_files/mydata') as shelf_file: file_name = os.path.basename(image_url) shelf_file[anime_title] = { 'episodes': episodes, 'completed': completed, 'ongoing': ongoing, 'image': file_name } # save the image if os.path.exists(f'./images/{file_name}') != True: image_file = open(os.path.join('images', file_name), 'wb') for chuck in image.iter_content(100000): image_file.write(chuck) image_file.close() else: pass
Я знаю, это много кода Но я обещаю, что мы почти закончили. Этот код имеет две функции, Download_webpage
и Download_Details
Отказ Download_webpage
использует Запросы
Для скачивания текста из данного URL. Затем текст анализируется на BeautifulSoup, которая позволяет нам выбрать элементы. Download_Details
Затем принимает этот анализируемый текст и выбирает элементы (имя аниме, количество эпизодов и т. Д.). Мы снова используем запросы, чтобы получить источник изображения и загрузить изображение и сохранить его в папке с именем изображения.
И это то, что для веб-соскабливания. Теперь до конца приложения.
Заканчивая заявлением
Модифицировать main.py
:
#... from scrap import download_webpage # new import from threading import Thread # new import # modify MainWindow class class MainWindow(MDScreen): #... # add new method def get_anime_info(self): '''Get the anime info and creates a list item widget and adds it to screen''' # open shelve files and get the urls with shelve.open('./save_files/mydata') as shelf_file: url_list = shelf_file['url_list'] # download data from each url for url in url_list: download_webpage(url) # after downloading the data and saving it shelve file get the data and display it with shelve.open('./save_files/mydata') as shelf_file: for key in shelf_file.keys(): if key != 'url_list': print(key) anime = shelf_file[key] episodes = anime['episodes'] completed = anime['completed'] image = anime['image'] anime_complete = 'completed' if completed else 'ongoing' # create a list item with the data list_item = ThreeLineAvatarIconListItem(text=key, secondary_text=f"[b]Status:[/b] {anime_complete}", tertiary_text=f"[b]Episodes:[/b] {episodes}") #add image to the list item list_item.add_widget(ImageLeftWidget(source=f"./images/{image}")) # finally add the list item to screen self.ids.box.add_widget(list_item)
Импортируйте функцию соскабливания из Scrap.py
и Нить
от резьба
Модуль, который мы собираемся использовать позже. Далее мы добавляем новый метод для MainWindow
Отказ Этот метод будет нести ответственность за загрузку и отображение информации аниме каждый раз, когда мы обновляем. Во-первых, он собирается получить URL-адреса, которые были сохранены в полке. Это пройдет эти URL для Download_webpage
функция. Эта функция будет загружать все данные аниме и сохранить информацию в файле SLALVE. После этого информация извлекается из файла SHALVE и, наконец, элементы списка создаются и добавлены на экран.
Теперь для окончательного дополнения, чтобы все работало.
#main.py # Modify MainWindow class MainWindow(MDScreen): # modify refresh_callback def refresh_callback(self, *args): print("Refreshing...") # new addition def refresh_callback(): self.ids.box.clear_widgets() # call the get_anime_info method self.get_anime_info() self.ids.refresh_layout.refresh_done() anime_thread = Thread(target=refresh_callback) anime_thread.start()
Мы изменим main.py
добавление Refresh_Callback
функция внутри другого Refresh_Callback
функция. Теперь, когда мы обновляем (Swipe Down), функция называется, и данные аниме загружаются и отображаются:
Приложение завершено! Теперь вы можете быть в курсе вашего любимого аниме. Сейчас иди, посмотрите кто-нибудь один ударман.
Отказ от ответственности: Это только для чистой образовательной цели. Не используйте это никакого способа, которые могут быть признаны атакующими Gogoanime Отказ
Полный код доступен здесь
Оригинал: “https://dev.to/ngonidzashe/created-an-anime-data-scraping-application-with-kivymd-and-bs4-cm4”