Last active
February 13, 2024 16:19
-
-
Save andmerk93/b0ebc144f53467e51db208065574c79a to your computer and use it in GitHub Desktop.
Скрипт на Selenium, чтоб скачать книжки в fb2 из своей библиотеки Litres
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
''' | |
Скрипт на Selenium, чтоб скачать книжки в fb2 | |
из своей библиотеки Litres. | |
Скрипт сам не скачивает книги, | |
только генерит txt-список прямых ссылок. | |
По списку ссылок потом отлично отрабатывает | |
плагин DownThemAll для Firefox. | |
Программа запускает существующую версию firefox, | |
где уже есть сохранненные логин и пароль, | |
пристегивает к ней geckodriver, а к нему Selenium. | |
При падении, завершает процессы, выжидает время, | |
и автоматически запускает заново. | |
''' | |
from datetime import datetime as dt | |
from subprocess import Popen | |
import time | |
from selenium.webdriver import FirefoxOptions, Remote | |
from selenium.webdriver.common.by import By | |
from selenium.webdriver.common.keys import Keys | |
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException | |
def print_time(num): | |
''' | |
Печать в консоль порядкового номера книжки (файла) | |
и времени выполнения загрузки | |
''' | |
print(num, (dt.now() - start_time).seconds, 'sec') | |
def parse_books_urls(driver, *args): | |
''' | |
Функция получения прямых ссылок | |
на страницы книг из коллекции. | |
Просто листает страницу до конца, | |
пока новые элементы появляются. | |
''' | |
elems_quantity = 0 | |
elems = 0 | |
while True: | |
elems = driver.find_elements(By.CLASS_NAME, 'ArtsGrid-module__artWrapper_1j1xJ') | |
if elems_quantity == len(elems): | |
elems_quantity = len(elems) | |
break | |
elems_quantity = len(elems) | |
try: | |
driver.find_element(By.CLASS_NAME, 'MyBooksWrapper-module__content_1NbYR').send_keys(Keys.END) | |
# Нужно было заменить на конкретный Exception | |
# Селениума, но я это своевременно не сделал | |
except Exception: | |
continue | |
return elems | |
def parse_direct_link(driver, url): | |
''' | |
Рекурсивная функция, которая получает прямую ссылку | |
на загрузку книги в fb2. | |
Рекурсия нужна для повторения в случае ошибки. | |
''' | |
driver.get(url) | |
try: | |
big_list = [ | |
i.get_attribute('href') | |
for i in driver.find_elements(By.TAG_NAME, 'a') | |
] | |
except StaleElementReferenceException: | |
print('Got error') | |
return parse_direct_link(driver, url) | |
for i in big_list: | |
if (i is not None) and ('fb2.zip' in i): | |
return i | |
return '' | |
def write_direct_links(driver, elems, start=0): | |
''' | |
Функция получает прямые ссылки fb2, | |
пишет их в консоль и в файл | |
Переменная start - порядковый номер книжки (файла) | |
Использовалась при падении браузера, когда отлаживал функцию | |
''' | |
with open('parsed_links.txt', '+a') as file: | |
for num, url in enumerate(elems[start:]): | |
print_time(num + start) | |
link = parse_direct_link(driver, url) | |
file.write(link + '\n') | |
def runner(func, elems=[]): | |
firefox = Popen( | |
('C:\\Program Files\\Mozilla Firefox\\firefox.exe', '-start-debugger-server', '2828', '-marionette') | |
) | |
geckodriver = Popen( | |
('D:\\python\\geckodriver.exe', '--connect-existing', '--marionette-port', '2828') | |
) | |
driver = Remote( | |
command_executor='http://127.0.0.1:4444', | |
options=FirefoxOptions() | |
) | |
driver.get('https://www.litres.ru/my-books/purchased/') | |
driver.implicitly_wait(0.5) | |
try: | |
func(driver, elems) | |
except TimeoutException: | |
geckodriver.terminate() | |
firefox.terminate() | |
print('Im fall :(') | |
time.sleep(300) | |
if __name__ == '__main__': | |
time.sleep(0) | |
start_time = dt.now() | |
book_urls = runner(parse_books_urls) | |
runner(write_direct_links, book_urls) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment