Использование Python и wget для извлечения текста и файлов

Плюсы и минусы использования Wget, ситуации когда лучше воспользоваться альтернативой.
Wget - это бесплатная, с 25-летней историей, программа командной строки, которая может извлекать текст и файлы с сайтов по протоколам HTTP, HTTPS и FTP. Если использовать его с Python, то практически нет никаких ограничений в парсинге данных с сайтов.

Эта статья покажет преимущества использования Wget с Python с некоторыми простыми примерами.

Преимущества wget

Wget позволяет загружать контент по трем протоколам: HTTP, HTTPS и FTP. Wget обязан своей популярностью двум своим основным особенностям: рекурсивности и надежности.

Рекурсивность. Используя правильные параметры wget может работать как веб-сканер. Вместо того, чтобы загрузить контент только с одной страницы, он может рекурсивно загружать весь контент, проходя по всем ссылкам с определенной страницы или пока не достигнет заданной пользователем глубины рекурсии. В этом сценарии wget сохраняет загруженные файлы в структуре каталога, точно воспроизводя структура каталога сервера, с которого они были загружены.

Wget:
  • поддерживает подстановочные знаки в сетевых местоположениях и именах файлов
  • предлагает проверку меток времени, чтобы загружать только новые или обновленные файлы
  • соблюдает стандарт исключения роботов (robots.txt)

Надежность. Wget может восстанавливаться после ошибок, что делает его хорошим решением для загрузки файлов через нестабильные или медленные сети. Wget использует заголовоки HTTP для продолжения загрузки с того места, где он остановился, до тех пор, пока не будет получен весь файл.

Wget2 был выпущен в 2021 году. Хотя он поддерживает более или менее те же функции, он фокусируется на распараллеливании, что делает его намного быстрее, чем его предшественник.

Wget плюс Python

Python - это язык программирования общего назначения, используемый в финансах, науке, data science, веб-разработке и автоматизации. Он имеет огромное сообщество, является самым популярным языком программирования и является одним из самых востребованных языков программирования в опубликованных вакансиях.

Используя Wget, вы можете легко превратить скрипты Python в полноценные решения для сканирования веб-страниц. Вот некоторые интересные сценарии использования:
  • создание наборов данных для академических и бизнес-целей. Через Wget легко спарсить содержимое одного или нескольких веб-сайтов. Эти большие наборы данных могут иметь важное значение для исследований в области машинного обучения. Например, последние модели NLP были бы невозможны без миллиардов фрагментов контента.
  • Мониторинг крупных веб-сайтов. Автоматизируйте Wget, чтобы проверить, доступны ли веб-страницы и файлы из разных сетей и мест по всему миру.
  • Сопоставление контента. Многие веб-страницы генерируют персонализированный контент. Настроив Wget так, чтобы он вел себя как разные личности. Вы сами выбираете какой контент отображать для вас.
Хотя существует несколько способов запуска команд оболочки и программ (например, Wget) в Python, здесь будем использовать пакет subprocess для взаимодействия с оболочкой операционной системы.

Обратите внимание, что пакет Python wget не связан с программой командной строки Wget. Это незаконченный пакет, который не обновлялся в течение многих лет.

Предварительная настройка

Во-первых, убедитесь, что на вашем компьютере установлен Wget. Этот процесс отличается в зависимости от вашей операционной системы.
  • Если вы используете Linux, возможно, он уже предустановлен.
  • Если вы используете Mac, самый простой способ установить Wget - использовать Homebrew.
  • Пользователи Windows могут загрузить исполняемый файл инструмента командной строки Wget с этого веб-сайта. После загрузки убедитесь, что он добавлен в переменную PATH.

Subprocess

Чтобы запустить команды Wget из сценария Python, будем использовать метод Popen пакета Subprocess. Каждый раз, когда скрипт вызывает popen(), он будет выполнять команду, которую мы передали в независимом экземпляре командного процессора операционной системы. Установив подробный аргумент в True, он также вернет выходные данные команды.
import subprocess

def runcmd(cmd, verbose = False, *args, **kwargs):

    process = subprocess.Popen(
        cmd,
        stdout = subprocess.PIPE, 
        stderr = subprocess.PIPE,
        text = True, 
        shell = True
    )
    std_out, std_err = process.communicate()
    if verbose:
        print(std_out.strip(), std_err)
    pass

    
runcmd('echo "Hello, World!"', verbose = True)
Будем использовать команду wget, давать ей URL-адрес и предоставлять конкретные параметры:
wget \[options\] url
Руководство по wget здесь.

Чтобы загрузить файл с сервера, передайте команду wget и URL-адрес файла. Установите verbose значение True.
runcmd("wget https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png", verbose = True)
Из выходных данных команды можно заметить, что (1) через URL-адрес получаем IP-адрес сервера, (2) отправляем HTTP-запрос и (3) получаем код состояния 200 OK. Наконец (4) Wget сохраняет файл в каталоге, из которого выполняется сценарий, без изменения имени файла.

Чтобы загрузить файл в определенную папку, передайте wget префикс --directory-prefix или флаг -P, а затем папку назначения.
runcmd("wget --directory-prefix=download_folder https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png", verbose = False)
runcmd("wget -P download_folder https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png", verbose = False)
Чтобы изменить папку назначения для файла и указать локальное имя файла. необходимо прописать флаг --output-document или -O и желаемое имя файла.
runcmd("wget -O logo.png https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png")
runcmd("wget --output-document=logo.png https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png")
Иногда нужно загрузить файл только в том случае, если локальная копия старше версии на сервере. Чтобы реализовать эту функцию, добавим опцию --timestamping
runcmd("wget --timestamping https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png", verbose = True)
Завершение прерванных загрузок. По умолчанию Wget повторяет попытку загрузки файла, если прервалось соединение. Однако, если вы хотите продолжить получать частично загруженный файл, то установите параметр -c или --continue.
runcmd("wget -c https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png")
runcmd("wget --continue https://cdn1.ozone.ru/s3/cms/57/t31/wc200/doodle_2.png")
Рекурсивный поиск - одна из важных функций Wget. Wget может парсить страницу по заданному URL-адресу, а также файлы, на которые ссылается этот документ, с помощью атрибутов HTML src и href или функциональной нотации CSS url().
Если следующий файл также является текстовым (HTML), он будет обработан и процесс не завершится до тех пор, пока не будет достигнута желаемая глубина рекурсии.

Вот некоторые опции, которые можно установить:

-r или --recursive включает рекурсивный поиск.

-l или --level позволяет установить глубину, т. е. количество подкаталогов, которые Wget может рекурсивно просмотреть. Чтобы предотвратить сканирование огромных веб-сайтов, Wget устанавливает глубину по умолчанию 5. Измените эту опцию на ноль (0) или «inf» для бесконечной глубины. Если вы хотите убедиться, что все необходимые ресурсы (изображения, CSS, JavaScript) загружены для правильного отображения страницы, даже если эти ресурсы не имеют требуемой максимальной глубины, вы можете установить -p или --page-requisites.

-k или --convert-links преобразует ссылки в загруженных документах, делая их пригодными для локального просмотра. Ссылки в загруженных файлах будут относительными (например, ../foo/bar.png). Файлы, которые не были загружены, будут называться по имени хоста.

Следующая команда рекурсивно загрузит веб-сайт https://tocomm.ru/в каталог www.tocomm.ru с максимальной глубиной 3\ Wget также преобразует все ссылки, чтобы сделать эту копию доступной локально.
runcmd('wget --recursive --level=3 --convert-links https://www.tocomm.ru')

Когда лучше не использовать Wget

Wget - отличное решение, если требуется рекурсивная загрузке файлов с веб-серверов. Тем не менее, его сценарии использования ограничены из-за этой узкой направленности.

Вот некоторые альтернативы:
  • Если вам нужно спарсить только определенные элементы DOM на веб-странице без локального хранения файлов, рассмотрите requests в сочетании с Beautiful Soup.
  • Selenium - это замечательное решение парсинга SPA, а также моделирования кликов, прокрутки страниц, заполнения форм и т.д.
Wget - это удобное решение для загрузки файлов по протоколам HTTP и FTP. Он хорошо работает с Python при рекурсивной загрузке, и процесс может быть легко автоматизирован.

Нужен парсинг сайтов?