Как парсить данные с Python: Requests, BeautifulSoup, Scrapy

    Команда Simple-Server
    03.06.2026
    14 мин

    Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.

    Кратко о задаче

    Любой документ, написанный на HTML, состоит из тегов двух типов:

    • Открывающий. Указывается внутри символов меньше (<) и больше (>). Например, <div>.

    Открывающий. Указывается внутри символов меньше (<) и больше (>). Например, <div>.

    • Закрывающий. Указывается в внутри символов меньше (<) и больше (>) с указанием косой черты (/). Например, </div>.

    Закрывающий. Указывается в внутри символов меньше (<) и больше (>) с указанием косой черты (/). Например, </div>.

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

    • href. Ссылка на ресурс. Например, href="https://simple-server.tech".

    href. Ссылка на ресурс. Например, href="https://simple-server.tech".

    • class. Класс объекта. Например, class="surface panel panel_closed".

    class. Класс объекта. Например, class="surface panel panel_closed".

    • id. Идентификатор объекта. Например, id="menu".

    id. Идентификатор объекта. Например, id="menu".

    Каждый тег с атрибутами (и без них) является элементом (объектом) так называемого дерева DOM (Document Object Model), которое строится практически любым интерпретатором (процессором) HTML-разметки.

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

    Например, в браузере доступ к элементам и их атрибутам выполняется через скрипты JavaScript. А в Python для этого применяются отдельные библиотеки.

    Разница лишь в том, что браузер после парсинга HTML-документа не просто строит DOM-дерево, а также выполняет его отображение на мониторе.

    Простой HTML-документ может выглядеть так:

    <!DOCTYPE html> <html> <head> <title>Это название страницы</title> </head> <body> <h1>Это заголовок</h1> <p>Это простой текст.</p> </body> </html>

    Разметка этой страницы построена на тегах с соблюдением иерархии без указания каких-либо атрибутов:

    • html
    * `head` * `title` * `body` * `h1` * `p`

    Такой структуры документа уже более чем достаточно для извлечения информации. Считывая данные между открывающим и закрывающим тегами, можно выполнять парсинг.

    Однако теги реальных сайтов имеют дополнительные атрибуты, указывающие браузеру как на специфическую функцию конкретного элемента, так и на его особое оформление (которое описывается в отдельных CSS-файлах):

    Таким образом, помимо явно указанных тегов искомую информацию можно уточнять конкретными атрибутами, вычленяя из дерева DOM только необходимые элементы.**
    **

    Устройство парсера данных HTML

    Страницы сайтов в сети интернет могут быть двух типов:

    • Статические. В процессе загрузки и просмотра сайта HTML-разметка остается неизменной. Парсинг не требует эмуляции работы браузера.

    Статические. В процессе загрузки и просмотра сайта HTML-разметка остается неизменной. Парсинг не требует эмуляции работы браузера.

    • Динамические. В процессе загрузки и просмотра сайта (Single-page application, SPA) HTML-разметка модифицируется с помощью JavaScript. Парсинг требует эмуляции работы браузера.

    Динамические. В процессе загрузки и просмотра сайта (Single-page application, SPA) HTML-разметка модифицируется с помощью JavaScript. Парсинг требует эмуляции работы браузера.

    Парсинг статических сайтов довольно прост — выполняется удаленный запрос, после чего из полученного HTML-документа извлекаются необходимые данные.

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

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

    Большинство современных сайтов так или иначе подгружают дополнительный контент с помощью скриптов на JavaScript.

    Вариативность технических реализаций современных сайтов настолько велика, что их нельзя назвать ни полностью статическими, ни полностью динамическими.

    Как правило, общая информация загружается сразу, а специфическая — уже потом.

    Большинство HTML-парсеров заточены под статические страницы. Системы, эмулирующие работу браузера для генерации динамического контента встречаются гораздо реже.

    В языке Python библиотеки (пакеты), предназначенные для анализа HTML-разметки, можно разделить на две группы:

    • Низкоуровневые процессоры. Компактные, но синтаксически запутанные пакеты со сложной реализацией, которые выполняют разбор синтаксиса HTML (или XML) и строят иерархическое дерево элементов.

    Низкоуровневые процессоры. Компактные, но синтаксически запутанные пакеты со сложной реализацией, которые выполняют разбор синтаксиса HTML (или XML) и строят иерархическое дерево элементов.

    • Высокоуровневые библиотеки и фреймворки. Обширные, но синтаксически лаконичные пакеты, обладающие широким набором функций для извлечения формализованных данных из сырых HTML-документов. В эту группу входят не только компактные HTML-парсеры, но и полноценные системы сборки. Зачастую такие пакеты в качестве ядра парсинга используют низкоуровневые пакеты (процессоры) из предыдущей группы.

    Высокоуровневые библиотеки и фреймворки. Обширные, но синтаксически лаконичные пакеты, обладающие широким набором функций для извлечения формализованных данных из сырых HTML-документов. В эту группу входят не только компактные HTML-парсеры, но и полноценные системы сборки. Зачастую такие пакеты в качестве ядра парсинга используют низкоуровневые пакеты (процессоры) из предыдущей группы.

    Для Python написано несколько низкоуровневых библиотек:

    • lxml. Низкоуровневый процессор синтаксиса XML, который также используется для анализа HTML. В его основе лежит популярная библиотека libxml2, написанная на языке C.

    lxml. Низкоуровневый процессор синтаксиса XML, который также используется для анализа HTML. В его основе лежит популярная библиотека libxml2, написанная на языке C.

    • html5lib. Библиотека анализа синтаксиса HTML, написанная на чистом Python в соответствии с HTML-спецификацией от организации WHATWG (The Web Hypertext Application Technology Working Group), которой следуют все современные браузеры.

    html5lib. Библиотека анализа синтаксиса HTML, написанная на чистом Python в соответствии с HTML-спецификацией от организации WHATWG (The Web Hypertext Application Technology Working Group), которой следуют все современные браузеры.

    Тем не менее, использование высокоуровневых библиотек быстрее и проще — их синтаксис понятнее, а набор функций шире:

    • BeautifulSoup. Простая, но гибкая библиотека для Python, позволяющая парсить документы на HTML и XML путем создания полноценного DOM-дерева элементов с последующим извлечением необходимых данных.

    BeautifulSoup. Простая, но гибкая библиотека для Python, позволяющая парсить документы на HTML и XML путем создания полноценного DOM-дерева элементов с последующим извлечением необходимых данных.

    • Scrapy. Полноценный фреймворк парсинга данных из HTML-страниц, представляющий собой набор автономных «пауков» (веб-краулеров) с заданными инструкциями.

    Scrapy. Полноценный фреймворк парсинга данных из HTML-страниц, представляющий собой набор автономных «пауков» (веб-краулеров) с заданными инструкциями.

    • Selectolax. Довольно быстрый парсер HTML-страниц, использующий так называемые CSS-селекторы для извлечения информации из тегов.

    Selectolax. Довольно быстрый парсер HTML-страниц, использующий так называемые CSS-селекторы для извлечения информации из тегов.

    • Parsel. Библиотека со специфическим синтаксисом селекторов, написанная на Python, позволяющая извлекать данные из документов на HTML, JSON и XML.

    Parsel. Библиотека со специфическим синтаксисом селекторов, написанная на Python, позволяющая извлекать данные из документов на HTML, JSON и XML.

    • requests-html. Удобная библиотека, написанная на Python, которая практически точь-в-точь имитирует браузерные CSS-селекторы языка JavaScript.

    requests-html. Удобная библиотека, написанная на Python, которая практически точь-в-точь имитирует браузерные CSS-селекторы языка JavaScript.

    В этом руководстве будет рассмотрено несколько подобных высокоуровневых библиотек.**
    **

    Установка пакетного менеджера pip

    Все библиотеки парсинга (впрочем, как и многие другие пакеты) в Python загружаются через стандартный пакетный менеджер pip — его потребуется установить отдельно.

    Для начала рекомендуется обновить список доступных репозиториев:

    А уже потом выполнить установку самого pip через пакетный менеджер APT:

    sudo apt install python3-pip -y

    Флаг -y позволит утвердительно ответить на все вопросы консольного терминала, возникающие во время установки.

    Корректность установки можно проверить, запросив версию pip:

    После этого в консольном терминале появится сообщение с версией пакетного менеджера и адресом его установки:

    pip 22.0.2 from /usr/lib/python3/dist-packages/pip (python 3.10)

    Как видно, в этом руководстве используется pip версии 22.0.2.**
    **

    Установка пакета HTTP-запросов

    Как правило, к интерпретатору Python по умолчанию прилагается стандартный пакет Requests , позволяющий совершать запросы к удаленным серверам. Именно он будет использоваться в примерах из этого руководства.

    Однако в некоторых случаях его может не быть. Поэтому рекомендуется вручную установить Requests через пакетный менеджер pip:

    Если пакет уже присутствует в системе, то в консольном терминале появится такое сообщение:

    Requirement already satisfied: requests in /usr/lib/python3/dist-packages (2.25.1)

    В противном случае Requests будет загружен в список пакетов, доступных для импорта в скриптах Python.

    Установка пакета BeautifulSoup версии 4 выполняется через пакетный менеджер pip:

    pip install beautifulsoup4

    После этого библиотека станет доступна для импорта в скриптах Python. Однако для ее работы требуется дополнительно установить ранее описанные низкоуровневые процессоры HTML.

    Поэтому сперва установим lxml:

    В дальнейшем в коде приложения Python можно будет указать один из этих процессоров в качестве ядра парсера BeautifulSoup.

    В домашней директории создадим новый файл:

    После чего наполним его кодом:

    import requests # импортируем библиотеку удаленных запросов from bs4 import BeautifulSoup # импортируем библиотеку парсинга BeautifulSoup response = requests.get('https://simple-server.tech') # выполняем запрос к удаленному серверу Simple-Server page = BeautifulSoup(response.text, 'html5lib') # парсим ответ удаленного сервера, указывая в качестве процессора парсера библиотеку html5lib pageTitle = page.find('title') # извлекаем заголовок с тегами <title></title> print(pageTitle) # выводим заголовок с тегами print(pageTitle.string) # выводим заголовок без тегов print("") pageParagraphs = page.find_all('a') # извлекаем все ссылки с тегами <a></a> # выводим текст всех найденных элементов if len(pageParagraphs) >= 3: # выводим содержимое (без тегов) найденных ссылок for i in range(3): print(pageParagraphs[i].string) print("") pageItemprop = page.find_all(itemprop='sameAs') # извлекаем все теги, содержащие атрибут itemprop со значением sameAs # выводим значения атрибута href всех найденных элементов for item in pageItemprop: print(item['href']) print("") pageMetas = page.find('div', itemprop='address').find_all('meta') # извлекаем все теги meta, размещенные внутри элемента div с атрибутом itemprop, значение которого равно address # выводим значения атрибута content всех найденных элементов for meta in pageMetas: print(meta['content'])

    Теперь можно запустить скрипт:

    Результатом его работы станет вот такой консольный вывод:>

    Разумеется, вместо html5lib можно указывать lxml:

    ... page = BeautifulSoup(response.text, 'lxml') ...

    Однако лучше всего в качестве процессора использовать библиотеку html5lib. В отличие от lxml, которая заточена исключительно под работу с XML-разметкой, html5lib была разработана с учетом всех современных стандартов HTML5.

    Несмотря на то, что библиотека BeautifulSoup имеет лаконичный синтаксис, она не поддерживает эмуляцию браузера, а значит не способна динамически подгружать контент.**
    **

    Фреймворк Scrapy реализован в более объектно-ориентированном виде. Парсинг сайтов в нем основан на трех базовых сущностях:

    • Пауки (Spiders). Классы, содержащие информацию о нюансах парсинга указанных сайтов: URL-адреса, селекторы (CSS или XPath) элементов и механизм просмотра страниц.

    Пауки (Spiders). Классы, содержащие информацию о нюансах парсинга указанных сайтов: URL-адреса, селекторы (CSS или XPath) элементов и механизм просмотра страниц.

    • Элементы (Items). Переменные для хранения извлеченных данных, представляющие собой более сложную форму словарей Python с особой внутренней структурой.

    Элементы (Items). Переменные для хранения извлеченных данных, представляющие собой более сложную форму словарей Python с особой внутренней структурой.

    • Каналы (Pipelines). Промежуточные обработчики извлеченных данных, способные изменять элементы и взаимодействовать с внешним ПО (например, базами данных).

    Каналы (Pipelines). Промежуточные обработчики извлеченных данных, способные изменять элементы и взаимодействовать с внешним ПО (например, базами данных).

    Установка Scrapy выполняется через пакетный менеджер pip:

    После этого необходимо инициализировать проект парсера, тем самым создав отдельную директорию со своей структурой каталогов и конфигурационных файлов:

    scrapy startproject parser

    Теперь можно перейти в только что созданную директорию:

    Проверим содержимое текущего каталога:

    Он состоит из общего конфигурационного файла и директории с исходниками проекта:

    Если проверить ее содержимое:

    -— то можно увидеть как специальные скрипты Python, каждый из которых выполняет свою функцию, так и отдельный каталог для пауков:

    __init__.py  items.py  middlewares.py  pipelines.py  settings.py  spiders

    По умолчанию большая часть параметров закомментированы с помощью символа решетки (#). Для корректной работы парсера часть этих параметров необходимо раскомментировать, не изменяя указанные в файле значения по умолчанию:

    Так или иначе, для каждого конкретного проекта потребуется более точная конфигурация фреймворка. Поэтому список всех параметров, доступных для настройки, можно найти на отдельной странице в официальной документации.

    После этого можно сгенерировать нового паука:

    scrapy genspider timewebspider simple-server.tech

    В консольном терминале должно появиться сообщение о создании нового паука:

    Created spider 'timewebspider' using template 'basic' in module: parser.spiders.timewebspider

    Теперь, если проверить содержимое каталога с пауками:

    — то в нем можно увидеть пустые исходники нового паука:

    __init__.py  __pycache__  timewebspider.py nano spiders/timewebspider.py

    И наполним следующим кодом:

    from pathlib import Path # пакет для работы с файлами import scrapy # пакет фреймворка Scrapy class TimewebSpider(scrapy.Spider): # класс паука наследуется от класса Spider name = 'timewebspider' # имя паука def start_requests(self): urls = ["https://simple-server.tech"] for url in urls: yield scrapy.Request(url=url, callback=self.parse) def parse(self, response): open("output", "w").close() someFile = open("output", "a") # создаем новый файл dataTitle = response.css("title::text").get() # извлекаем заголовок из ответа сервера с помощью CSS-селектора dataA = response.css("a").getall() # извлекаем все ссылки из ответа сервера с помощью CSS-селектора someFile.write(dataTitle + "\n\n") for i in range(3): someFile.write(dataA[i] + "\n") someFile.close()

    Теперь можно запустить созданный паук:

    scrapy crawl timewebspider

    После этого в текущей директории появится файл output:

    Его содержимое будет следующим:

    Более подробную информацию об извлечении данных с помощью селекторов (как CSS, так и XPath) можно найти в официальной документации Scrapy.**
    **


    Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.

    VPS для проекта

    VPS с root-доступом, NVMe и поддержкой 24/7 на Simple-Server.

    StarterVDS

    490₽

    в месяц

    1 ядро

    1 ГБ RAM

    20 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Безлимитный трафик
    Заказать VPS
    Рекомендуем

    PerformanceVDS

    1190₽

    в месяц

    2 ядра

    4 ГБ RAM

    60 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Базовая DDoS-защита
    Заказать VPS

    Нужна другая конфигурация или чистый VPS без панели?

    Все тарифы VPS

    Похожие статьи, которые могут быть вам интересны