CoderCastrov logo
CoderCastrov
Selenium

Бесплатные книги Springer, поторопитесь!

Бесплатные книги Springer, поторопитесь!
просмотров
3 мин чтение
#Selenium

Springer позволяет нам скачать около 500 учебников во время вспышки Covid-19, и вот как я их получил с помощью кодирования. Читайте дальше...

Для тех, кто еще не прочитал новости, вот они: https://www.springernature.com/gp/librarians/news-events/all-news-articles/industry-news-initiatives/free-access-to-textbooks-for-institutions-affected-by-coronaviru/17855960

Я узнал об этом из одной из историй моих друзей на Facebook, и этот парень был достаточно любезен, чтобы также предоставить мне PDF-файл со всеми ссылками, которые я могу использовать для скачивания. Вы также можете найти его здесь: https://drive.google.com/file/d/1Of4RomN9qX_ufIFW86N5_LF8ivwfV2vC/view

В списке содержится 408 книг, это огромное количество. И у меня нет ни времени, ни терпения, чтобы скачивать их по одной. Поэтому пришло время запустить мою среду разработки и написать некоторый код, чтобы это сделать.


Настройка окружения

Теперь я использую Miniconda для управления виртуальными окружениями, но вы можете использовать свою собственную систему и создать новое окружение, я называю его springer-download.

После активации окружения я установил следующие библиотеки:

Кроме того, мне также необходимо скачать chromedriver отсюда here и сохранить его в той же папке проекта. Этот файл нужен для использования Selenium с моим браузером Chrome.

Разбор кода

Я постараюсь объяснить все функции, которые у меня есть, чтобы вы могли использовать их в любых своих будущих проектах. Однако, если вы просто хотите проверить финальный код, вот ссылка на репозиторий Github.

Разбор PDF и извлечение URL-адресов книг

PyPDF2 - это библиотека, которую я использую, если мне нужно извлечь текст из файла PDF. Однако, если вам нужно работать с отсканированными файлами PDF (где содержимое представлено в виде изображений), вам потребуется другая библиотека. В моем случае, PDF-файл, который я получил от друга, является простым текстовым PDF, поэтому все просто:

Я прошелся по всем страницам, преобразовал и объединил их в одну большую переменную text. Последний шаг - использовать библиотеку регулярных выражений Python для извлечения всех веб-страниц книг из этой переменной.

Функция-утилита для загрузки книги по ее URL-адресу

requests - это лучшая библиотека Python для работы с HTTP-клиентами, и здесь я использовал функцию stream для загрузки файла.


Функция для выбора элемента Selenium с учетом времени ожидания

Хорошо, вот факт. Когда вам нужно работать с веб-сканером и Selenium, идеально управлять элементами с помощью времени ожидания. Иногда веб-страница работает медленно, и если вы попытаетесь сразу получить доступ к элементу, код не сработает. Например, это не хороший фрагмент:

element = driver.find_element_by_id("myElement")

Поэтому у меня есть вспомогательная функция:

def find_element_with_timeout(driver, by, value, timeout=10):
    wait = WebDriverWait(driver, timeout)
    return wait.until(EC.presence_of_element_located((by, value)))

Вспомогательная функция для запуска браузера Chrome

Для этого простого проекта я использовал минимальную настройку для браузера Chrome:

from selenium import webdriver

def start_chrome_browser():
    options = webdriver.ChromeOptions()
    options.add_argument("--headless")
    options.add_argument("--disable-gpu")
    options.add_argument("--no-sandbox")
    return webdriver.Chrome(options=options)

Функция для загрузки книги по ее странице на Springer

PDF-файл, который у меня есть, содержит ссылки на веб-страницы книг, а не их прямые URL-адреса для загрузки. Поэтому мы напишем еще одну функцию, которая будет выполнять следующие задачи:

def download_book(driver, book_page_url):
    driver.get(book_page_url)
    # Найдите ссылку на загрузку книги на странице
    download_link = find_element_with_timeout(driver, By.XPATH, "//a[contains(text(), 'Download')]")
    download_link.click()
    # Дождитесь загрузки файла
    time.sleep(10)

Объединение всего в основную функцию

Учитывая все функции выше, довольно просто объединить логику. Нам понадобится:

def main():
    # Получить список книг
    books = get_book_list()

    # Создать папку для загрузки
    create_download_folder()

    # Скачать все книги
    download_books(books)

if __name__ == "__main__":
    main()

Финальные мысли

Мне понадобилось около 20 минут, чтобы написать этот код, и мой ноутбук потратил еще 2 часа на загрузку всех книг. Предполагая, что я попытаюсь загрузить их вручную, каждая книга займет около 40 секунд, и я потратил бы примерно 5,5 часов подряд.

Существуют и другие способы выполнить эту задачу (например, использовать API Springer CMS или загрузить файл Excel с аналогичной информацией). Однако в этой статье я просто хочу показать вам общий метод, который можно использовать и для других веб-сайтов. Надеюсь, вы сможете уловить идею и применить ее в своих проектах. И на всякий случай, вот репозиторий Github еще раз.

Cheers, ❤️