Автоматизация парсинга плейлистов YouTube с помощью Python и Selenium
Если вы хотите автоматизировать парсинг списков воспроизведения YouTube для вашего следующего личного проекта или внештатного клиента, этот блог поможет вам и проведет вас через каждый шаг от импорта соответствующих библиотек до написания кода драйвера.
Язык программирования: Python🐍
Среда парсинга/автоматизации: Selenium
Давайте начнем и пройдемся по каждому шагу. 😍
Импорт соответствующих библиотек
Что касается библиотек, я не использовал никаких причудливых библиотек или модулей. Остановимся на основных. Ниже приведены библиотеки, которые я импортировал, и почему.
- из selenium import webdriver
(библиотека selenium в Python предоставляет способ автоматизации взаимодействия с веб-браузером, а модуль webdriver специально позволяет вам программно управлять веб-браузером.) - from selenium.webdriver.common.by import By
(Класс By в модуле selenium.webdriver.common.by обеспечивает способ указать различные методы поиска элементов HTML на веб-странице, например, по идентификатору, имени класса или селектору CSS.) - время импорта
(предоставляет функции для работы с операциями, связанными со временем, такими как получение текущего времени, ожидание в течение определенного периода времени и форматирование значений времени.) - из модуля записи импорта csv
(это модуль Python, используемый для работы с файлами CSV (значения, разделенные запятыми), в частности для импорта записи strong>, который позволяет записывать данные в CSV-файлы с использованием разделителя-запятой.) - import pandas as pd
(это библиотека Python, используемая для обработки и анализа данных, предоставляющая структуры данных и функции для работы с табличными данными.) - из selenium.webdriver.common.keys import Keys
(это модуль из библиотеки Python Selenium, используемый для имитации клавиш клавиатуры, в частности импортирующий класс Keys, который предоставляет набор предопределенных клавиш, которые можно использовать для различных действий с клавиатурой.)
Теперь, надеюсь, понятно, почему эти библиотеки были импортированы, давайте перейдем к фактическому коду и разберем шаги. Я также поделюсь некоторыми ошибками и проблемами, с которыми я столкнулся, и тем, как я их преодолел, и вы тоже можете это сделать.
Выполнение
Для реализации я использовал язык программирования Python. Я использовал объектно-ориентированный подход, который, во-первых, является профессиональным подходом, а во-вторых, основой чистого кода.
Другой важный принцип, который я использовал, и этот принцип очень важен для всех разработчиков программного обеспечения и программистов, — это принцип SOLID. Но я не реализовал все SOLID, я сосредоточился на двух: S (принцип единой ответственности) и O (открыт для расширения, но закрыт для модификации).
Теперь я пройдусь по каждому классу, объясню работу и постараюсь быть кратким. 😉
- Инициализатор класса:
(Класс инициализатора инициализирует пустой список, т. е. список ключевых слов. Этот список ключевых слов будет использоваться во всем коде, поэтому вместо того, чтобы определять его везде, я инициализировал его в начале.) - Класс Browser:
(класс браузера отвечает за создание сеанса браузера, т. е. за открытие браузера Chrome.) - Класс Scraper:
(Класс Scraper имеет 2 метода: поиск и сбор плейлиста. Метод поиска ищет ключевое слово на YouTube, а метод скрапинга плейлиста извлекает необходимые детали плейлиста.) - Класс CSV:
(Класс CSV отвечает за все методы, связанные с CSV-файлом. Он имеет 3 метода: read csv, который считывает входной csv, make csv, который создает выходной csv с заголовком столбца, и третий метод заполнить csv, который заполняет выходной csv данными плейлиста.) - Класс Scraper Implementor:
(класс реализации Scraper отвечает за реализацию всех вышеперечисленных классов с использованием наследования и вызовом всех методов из вышеуказанных классов.)
Итак, как на самом деле работает код? 🤷
Работающий
Остановимся на сути,
- Код считывает входной CSV-файл (вы можете назвать его как хотите) и добавляет ключевые слова из этого CSV-файла в список ключевых слов.
- Метод make csv создает файл CSV (вы можете назвать его как хотите) с заголовком столбца. Этот метод make csv вызывается перед циклом, потому что я не хочу создавать новый файл csv каждый раз, когда выполняется цикл for.
- Теперь выполните итерацию по каждому ключевому слову в списке ключевых слов.
- Объект класса браузера в классе реализации открывает браузер Chrome (вы можете изменить код класса браузера, чтобы открыть любой другой браузер по вашему выбору).
- Используя функцию get(), откройте целевой URL-адрес (в данном случае моим целевым URL-адресом была домашняя страница YouTube).
- Создайте объект метода поиска, определенный в классе Scraper. Это приведет к поиску ключевого слова на YouTube и отображению всех плейлистов, связанных с этим ключевым словом.
- Создайте еще один объект, но на этот раз для метода очистки плейлиста, определенного в классе Scraper. Этот метод сначала проверяет наличие текста на странице, т. е. «Больше результатов нет», пока этот текст не будет найден на странице, он продолжает прокручивать страницу с помощью клавиши «страница вниз». Selenium обрабатывает нажатия клавиш, вам не нужно нажимать их физически. При прокрутке он собирает информацию о плейлисте с помощью метода find_elements() (это встроенный метод селена, который используется, если какой-либо элемент встречается на странице более одного раза, и если вам нужны все эти элементы. Он возвращает список всех этих элементов). Как только текст найден, я перебираю каждый список деталей плейлиста и получаю его текст (изначально он хранит данные в виде объектов, нам нужно использовать текстовую функцию для преобразования этих объектов в текст. Вы также должны помнить, что вы можете используйте текстовую функцию только для одного объекта, поэтому, скажем, в моем случае у меня был список объектов, поэтому я перебирал список и преобразовывал каждый объект в текст один за другим через цикл).
- В конце метод populate csv помещает всю полученную информацию в выходной CSV.
КОД
from selenium import webdriver from selenium.webdriver.common.by import By import time from csv import writer import pandas as pd from selenium.webdriver.common.keys import Keys class Initializer: def __init__(self): self.keywords_lst = [] # A browser class which initializes browser class Browser: def session(self): self.driver = webdriver.Chrome() # a scraper class which performs search # and scrapes the playlist details class Scraper(Browser, Initializer): def search(self, keyword): search_field = self.driver.find_element(By.XPATH, "//input[@id='search']") search_field.click() time.sleep(2) search_field.send_keys(keyword) self.driver.find_element(By.XPATH, '//button[@class="style-scope ytd-searchbox"]').click() time.sleep(10) filters = self.driver.find_element(By.XPATH, '//ytd-toggle-button-renderer[@class="style-scope ytd-search-sub-menu-renderer"]') filters.click() time.sleep(2) set_filter = self.driver.find_element(By.XPATH, '//div[@title="Search for Playlist"]') self.driver.execute_script("arguments[0].click()",set_filter) time.sleep(5) def playlist_scraper(self): playlist_title = [] playlist_link = [] playlist_videos = [] flag = False while not flag: body = self.driver.find_element(By.TAG_NAME, "body") body.send_keys(Keys.PAGE_DOWN) time.sleep(1) # wait for the page to load new content playlist_title = self.driver.find_elements(By.XPATH, '//span[@id="video-title"]') playlist_link = self.driver.find_elements(By.XPATH, '//a[@class="yt-simple-endpoint style-scope ytd-playlist-thumbnail"]') playlist_videos = self.driver.find_elements(By.XPATH, '//yt-formatted-string[@class="style-scope ytd-thumbnail-overlay-side-panel-renderer"]') # check if there are no more results no_more_results = self.driver.find_elements(By.XPATH, "//*[contains(text(), 'No more results')]") if len(no_more_results) > 0: flag = True title_lst = [] for title in playlist_title: title_lst.append(title.text) playlist_link_lst = [] for link in playlist_link: playlist_link_lst.append(link.get_attribute('href')) playlist_videos_lst = [] for views in playlist_videos: playlist_videos_lst.append(views.text) self.new_title = [] self.new_playlist_link = [] self.new_playlist_videos = [] for i in title_lst: if i != "": self.new_title.append(i) for j in playlist_link_lst: if j != "": self.new_playlist_link.append(j) for k in playlist_videos_lst: if k != "": self.new_playlist_videos.append(k) print(title_lst) print(playlist_link_lst) print(playlist_videos_lst) # CSV class which performs all operations # related to CSV. (read the keywords csv, # make the output csv and populate each playlist # detail in the CSV. class CSV(Scraper, Initializer): def read_csv(self, filename): df = pd.read_csv(filename) for i in df['Keywords']: self.keywords_lst.append(i) def make_csv(self, filename): with open(filename, "a", encoding="utf8", newline="") as f: write_csv = writer(f) columns = ['Playlist Title', 'No.of Videos', 'Playlist Link'] write_csv.writerow(columns) def populate_csv(self,filename): with open(filename, "a", encoding="utf8", newline="") as f: write_csv = writer(f) for i,j,k in zip(self.new_title, self.new_playlist_videos, self.new_playlist_link): data = [i,j,k] write_csv.writerow(data) # An implementor class which calls all # the fucntions from above class and implements # Scraper class Scraper_Implementor(CSV): def get_playlist(self,read_filename,write_filename, url): super().read_csv(read_filename) print(self.keywords_lst) super().make_csv(write_filename) for i in self.keywords_lst: super().session() time.sleep(2) self.driver.get(url) time.sleep(5) super().search(keyword=i) super().playlist_scraper() super().populate_csv(write_filename) # Driver Code obj = Scraper_Implementor() obj.get_playlist('keywords.csv','test_v2.csv', 'https://www.youtube.com/')
Итак, это выше, вот фактическая закодированная реализация🙌
Давайте обсудим, с какими типами ошибок я столкнулся и как я их преодолел. 👀
- Ошибка JavaScript:
Сообщение: ошибка JavaScript: невозможно прочитать свойства неопределенного (чтение «DefaultView»)
Итак, эта ошибка возникала, когда селен пытался щелкнуть параметр плейлиста. Это происходило один раз из 5. Но вскоре я преодолел это, позволив JavaScript обрабатывать щелчок здесь. Во-первых, я позволял селену делать щелчок.
(Сценарий выше сейчас безошибочен 😊)
Заключительные примечания
Есть и другие способы парсинга сайтов, но это был один из них. Если вы хотите добавить к нему какую-либо функциональность, перейдите по ссылке репозитория. 👉 saad-24/Youtube-Scraper и не забудьте отметить этот репозиторий звездочкой 😉.