Закон и парсинг сайтов

Как научиться парсить открытые данные на сайтах с нуля: на Python и С# .NET Core

Содержание скрыть

Часть 1: Основы парсинга сайтов

Глава 1: Введение в парсинг: ваш шлюз в мир данных

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

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

Чтобы полностью понять, как работает веб-парсинг, важно различать несколько ключевых терминов, которые часто используются как взаимозаменяемые, но имеют разные значения.

На практике современный инструмент для веб-парсинга, как правило, выполняет все три задачи: он находит страницы (краулинг), анализирует их структуру (парсинг) и извлекает нужные данные (парсинг).5

Важно понимать, что парсинг — это не какая-то нишевая или сомнительная деятельность. Это фундаментальная технология, на которой построена значительная часть современного интернета. Крупнейшие технологические компании, включая Google и Facebook, являются, по сути, самыми масштабными веб-скрейперами в мире.6 Они каталогизируют информацию, чтобы сделать ее доступной через поиск или для построения социальных связей. Это понимание смещает фокус с вопроса «Можно ли это делать?» на вопрос «Как делать это ответственно и профессионально?».

Сферы применения веб-парсинга огромны и разнообразны:

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

Глава 2: Кодекс чести скрейпера: юридические и этические аспекты

Прежде чем написать хотя бы одну строчку кода, абсолютно необходимо усвоить правила игры. Парсинг находится в так называемой «серой зоне»: сам по себе он не является незаконным, но его правомерность сильно зависит от того, что и как вы собираете.10 Несоблюдение правил может привести к серьезным последствиям, от блокировки вашего IP-адреса до судебных исков и крупных штрафов.13 Эта глава — самая важная для вашей безопасности. Практика ответственного парсинга строится на трех основных принципах: уважение к правилам сайта, соблюдение законов об авторском праве и защита персональных данных.

Уважение к правилам сайта: robots.txt и Условия использования

Каждый веб-сайт — это частная собственность в цифровом мире. Как и в реальном мире, у владельца есть право устанавливать правила поведения на своей территории.

  • Файл robots.txt: Это текстовый файл, который находится в корневой директории сайта (например, https://example.com/robots.txt) и содержит инструкции для автоматизированных программ (ботов).14 В этом файле владелец сайта указывает, какие разделы сайта он не хотел бы, чтобы сканировали боты (
    Disallow), а какие можно (Allow), и с какой задержкой следует делать запросы (Crawl-delay).16 Важно понимать, что
    robots.txt — это не технический барьер, а скорее «просьба» или рекомендация. Уважающие себя краулеры, включая поисковые системы, следуют этим правилам, но технически их можно проигнорировать.14 Этичное поведение подразумевает строгое соблюдение этих указаний.8
  • Условия использования (Terms of Service, ToS): Это юридически обязывающий документ, который вы принимаете, просто заходя на сайт. Если в ToS прямо указан запрет на автоматический сбор данных, то парсинг этого сайта является нарушением договора и может повлечь за собой юридические последствия.19

Часто возникает ситуация, когда robots.txt разрешает сканирование (например, для поисковых систем), а Условия использования — запрещают. Этот конфликт создается намеренно: технический отдел хочет, чтобы сайт индексировался в Google, а юридический отдел — чтобы иметь основания для судебного преследования в случае нежелательного парсинга.22 В таких случаях юридический приоритет, как правило, имеют Условия использования. Это означает, что нельзя слепо доверять robots.txt, если ToS говорит обратное.

Авторское право и интеллектуальная собственность

Данные на сайтах часто защищены законами об авторском праве.23

  • Что можно и что нельзя парсить: Как правило, простые факты — такие как цены на товары, статистические данные, курсы валют — не являются объектом авторского права.12 Однако их творческое представление, например, уникальные описания товаров, статьи, фотографии, а также сама структура базы данных, могут быть защищены.24
  • Как использовать данные: Копирование защищенного контента и его публикация на своем ресурсе под видом собственного — это плагиат и прямое нарушение закона.20 Использование данных для внутреннего анализа, исследований или создания производных работ, которые не конкурируют напрямую с оригинальным сайтом, может подпадать под доктрину «добросовестного использования» (fair use), особенно в США.11 Однако это очень тонкая юридическая грань.

Персональные данные и конфиденциальность (GDPR, CCPA)

Это самый строгий и опасный аспект современного парсинга. Персональными данными (Personally Identifiable Information, PII) считается любая информация, которая может прямо или косвенно идентифицировать человека: имена, адреса электронной почты, номера телефонов, IP-адреса, геолокационные данные.3

  • Регулирование: Законы, такие как Общий регламент по защите данных (GDPR) в Европе и Калифорнийский закон о защите прав потребителей (CCPA), накладывают строжайшие ограничения на сбор и обработку персональных данных.10 Эти законы действуют независимо от того, где находитесь вы, если вы собираете данные граждан соответствующих юрисдикций.10
  • «Публично доступные» не значит «можно брать»: Даже если персональные данные находятся в открытом доступе (например, в профиле социальной сети), их автоматический сбор и хранение без явного согласия пользователя или другого законного основания является нарушением GDPR и может привести к огромным штрафам.11 Знаменитое дело
    hiQ vs. LinkedIn постановило, что парсинг общедоступных данных не нарушает законы о компьютерном мошенничестве, но это решение не отменяет требований законов о конфиденциальности, таких как GDPR.10

Этический кодекс скрейпера

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

  1. Не создавайте чрезмерную нагрузку: Агрессивный парсинг с большим количеством запросов в секунду может замедлить работу сайта или даже вывести его из строя, что равносильно DDoS-атаке.27 Всегда устанавливайте разумные задержки между запросами, парсите в часы наименьшей нагрузки (например, ночью) и запрашивайте только те данные, которые вам действительно нужны.6
  2. Идентифицируйте себя: Используйте в своих запросах заголовок User-Agent, который четко идентифицирует вашего бота (например, MyAwesomeScraper/1.0 (+http://mywebsite.com/bot-info)). Это позволяет администраторам сайта понять, кто вы, и связаться с вами в случае проблем.
  3. Сначала ищите API: Прежде чем приступать к парсингу, всегда проверяйте, не предоставляет ли сайт официальный API (Application Programming Interface). API — это «парадная дверь» для программного доступа к данным, и его использование всегда предпочтительнее, законнее и эффективнее.10
  4. В сомнениях — спросите: Если вы не уверены в правомерности своих действий, лучший способ — связаться с владельцами сайта и запросить разрешение.20

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

Контрольный пунктДействиеПочему это важно
Наличие APIПроверить, предлагает ли сайт публичный API?API — это предпочтительный, законный и наиболее эффективный способ получения данных.
Анализ robots.txtПрочитать и понять файл robots.txt?Демонстрирует уважение к пожеланиям владельца сайта и помогает избежать очевидно запрещенных разделов.
Условия использованияПрочитать Условия использования на предмет пунктов, запрещающих парсинг?ToS — это юридическое соглашение; его нарушение может иметь серьезные последствия.
Тип данныхСобираются факты или контент, защищенный авторским правом?Факты, как правило, можно собирать; защищенные материалы требуют разрешения или обоснования добросовестного использования.
Персональные данныеСодержат ли данные какую-либо персональную информацию (PII)?Сбор PII строго регулируется GDPR/CCPA и сопряжен с чрезвычайно высоким риском.
Частота запросовИспользуется ли разумная задержка между запросами?Предотвращает перегрузку сервера, что неэтично и может привести к бану IP-адреса.
ИдентификацияИспользует ли парсер понятный заголовок User-Agent?Обеспечивает прозрачность для администраторов сайта.

Соблюдение этих правил не только защитит вас от юридических рисков, но и сделает вас ответственным членом цифрового сообщества.

Часть 2: Подготовка вашей среды разработки

Глава 3: Настройка вашего набора инструментов

Прежде чем мы сможем начать извлекать данные, необходимо подготовить рабочее окружение. Этот процесс включает в себя установку языков программирования и их экосистем. Мы рассмотрим установку для двух платформ: Python и.NET Core, на трех основных операционных системах: Windows, macOS и Linux. Цель этого раздела — обеспечить успешную установку даже для абсолютного новичка.

Сам процесс установки выявляет фундаментальное различие в философии двух экосистем. Установка Python может быть более фрагментированной, с потенциальными конфликтами версий и путаницей между командами (python и python3, pip и pip3). Это отражает гибкость и децентрализованность мира open-source. С другой стороны, установка.NET более унифицирована и контролируется Microsoft, предлагая более структурированный и «все в одном» опыт с единым SDK и командой dotnet. Это не означает, что одна система лучше другой, но понимание этих различий помогает осознанно подходить к процессу.

Путь Python

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

Установка на Windows:

  1. Загрузка установщика: Перейдите на официальный сайт Python (https://www.python.org) и скачайте последнюю стабильную версию установщика для Windows.33 Сайт автоматически определит разрядность вашей системы (32-бит или 64-бит).
  2. Запуск установки: Запустите скачанный .exe файл. На первом экране установки появится критически важная опция.
  3. Добавление в PATH: Обязательно поставьте галочку напротив «Add Python to PATH».34 Этот шаг позволит вам запускать Python из любой папки в командной строке, что значительно упростит дальнейшую работу.
  4. Установка: Нажмите «Install Now» для стандартной установки, которая включает в себя pip — менеджер пакетов Python.33
  5. Проверка: Откройте командную строку (нажмите Win+R, введите cmd и нажмите Enter) и выполните команду python —version. Если вы видите номер установленной версии, значит, все прошло успешно.

Установка на macOS:

macOS часто поставляется с предустановленной старой версией Python 2, которую не следует использовать для новых проектов.

  1. Установка через Homebrew (рекомендуется): Homebrew — это популярный менеджер пакетов для macOS. Если он у вас не установлен, откройте Терминал и установите его. Затем выполните команду: brew install python.34 Этот способ упрощает управление версиями.
  2. Установка с официального сайта: Альтернативно, вы можете скачать установщик .pkg с официального сайта Python и следовать инструкциям.33
  3. Проверка: Откройте Терминал и введите команду python3 —version. Использование python3 вместо python гарантирует, что вы обращаетесь к установленной вами версии, а не к системной.33

Установка на Linux:

Большинство дистрибутивов Linux поставляются с предустановленным Python 3.

  1. Проверка версии: Откройте терминал и введите python3 —version.
  2. Установка/Обновление: Если Python не установлен или версия устарела, используйте менеджер пакетов вашего дистрибутива.
  • Для Debian/Ubuntu: sudo apt update && sudo apt install python3 python3-pip.34
  • Для Fedora: sudo dnf install python3.34
  • Для Arch Linux: sudo pacman -S python.34

Установка pip:

pip — это система управления пакетами, используемая для установки и управления программными пакетами, написанными на Python. Начиная с Python 3.4, pip обычно устанавливается вместе с Python.36

  • Проверка: В терминале или командной строке введите pip —version или pip3 —version.
  • Ручная установка (если необходимо): Если pip не установлен, его можно установить отдельно. Скачайте скрипт get-pip.py с официального сайта (https://bootstrap.pypa.io/get-pip.py), сохраните его и запустите из командной строки командой python get-pip.py.37

Путь.NET Core

.NET (ранее.NET Core) — это кроссплатформенная среда разработки от Microsoft, мощная и производительная, с отличной поддержкой для создания веб-приложений и сервисов.

Установка.NET SDK:

Основной инструмент, который вам понадобится, — это .NET SDK (Software Development Kit), который включает в себя все необходимое для разработки и запуска приложений.

  1. Загрузка установщика: Перейдите на официальную страницу загрузки.NET (https://dotnet.microsoft.com/download) и скачайте установщик SDK для вашей операционной системы.40
  2. Установка на Windows: Запустите скачанный .exe файл и следуйте простым инструкциям мастера установки.40
  3. Установка на macOS: Запустите скачанный .pkg файл и также следуйте инструкциям.40
  4. Установка на Linux: Для дистрибутивов на базе Debian/Ubuntu, как правило, необходимо добавить репозиторий пакетов Microsoft, а затем установить SDK с помощью apt:

    Bash
    sudo apt-get update
    sudo apt-get install -y apt-transport-https
    sudo apt-get update
    sudo apt-get install -y dotnet-sdk-8.0 # Замените на актуальную версию


    Аналогичные команды существуют и для других дистрибутивов, таких как Fedora (dnf) или CentOS (yum).40
  5. Проверка: После установки откройте терминал или командную строку и выполните универсальную команду dotnet —info. Она выведет подробную информацию об установленной версии SDK и среде выполнения, подтверждая успешную установку.

Теперь, когда базовые инструменты установлены, вы готовы к настройке среды разработки для написания кода.

Глава 4: Выбор и настройка вашей IDE

IDE (Integrated Development Environment) или интегрированная среда разработки — это текстовый редактор, «заряженный» дополнительными инструментами, которые упрощают написание, запуск и отладку кода. Правильно настроенная IDE значительно повышает продуктивность. Мы сосредоточимся на Visual Studio Code как на универсальном и мощном решении для обеих платформ, но также упомянем и другие популярные альтернативы.

Универсальный выбор: Visual Studio Code

Visual Studio Code (VS Code) — это бесплатный, легковесный и чрезвычайно расширяемый редактор кода от Microsoft, который стал стандартом де-факто для многих разработчиков благодаря своей кроссплатформенности и огромной экосистеме расширений.

Установка VS Code:

Перейдите на официальный сайт (https://code.visualstudio.com/) и скачайте установщик для вашей ОС (Windows, macOS, Linux).42 Процесс установки интуитивно понятен.

Настройка для разработки на Python:

  1. Установка расширения Python: Откройте VS Code, перейдите в панель расширений (иконка с квадратами на боковой панели или Ctrl+Shift+X), введите в поиске «Python» и установите официальное расширение от Microsoft. Оно предоставляет такие функции, как автодополнение кода (IntelliSense), отладку и анализ кода (linting).42
  2. Выбор интерпретатора Python: Нажмите Ctrl+Shift+P, чтобы открыть командную палитру, начните вводить «Python: Select Interpreter» и выберите эту команду. VS Code покажет список всех найденных на вашем компьютере версий Python. Выберите ту, которую вы установили в предыдущей главе.42
  3. Создание виртуального окружения (критически важно!): В Python является лучшей практикой изолировать зависимости каждого проекта в отдельном «виртуальном окружении». Это предотвращает конфликты между проектами, которым могут требоваться разные версии одной и той же библиотеки. В.NET управление зависимостями происходит на уровне проекта через NuGet, поэтому там этот шаг не так актуален в ручном режиме.
  • Откройте терминал в VS Code (`Ctrl+«).
  • Создайте окружение: python -m venv env (где env — имя папки окружения).
  • Активируйте его:
  • Windows: .\env\Scripts\activate.42
  • macOS/Linux: source env/bin/activate.42
  • VS Code автоматически предложит использовать интерпретатор из этого окружения.
  1. Запуск и отладка: Создайте файл script.py. Вы можете запустить его, нажав на кнопку «Play» в правом верхнем углу, или начать отладку, нажав F5.44 Отладчик позволяет устанавливать точки останова и пошагово выполнять код, что неоценимо при поиске ошибок.

Настройка для разработки на.NET Core:

  1. Установка расширения C# Dev Kit: Аналогично Python, откройте панель расширений, найдите и установите «C# Dev Kit» от Microsoft. Этот пакет включает в себя все необходимое для разработки на C#, включая поддержку проектов, отладку и IntelliSense.
  2. Создание проекта: Откройте терминал в VS Code и создайте новый проект консольного приложения: dotnet new console -n MyScraperApp. Затем откройте эту папку в VS Code (File -> Open Folder).
  3. Запуск и отладка: Откройте файл Program.cs. Нажмите F5, чтобы запустить приложение с отладкой. VS Code автоматически создаст необходимые файлы конфигурации для сборки и запуска.

Специализированные IDE (краткий обзор)

Хотя VS Code является отличным универсальным инструментом, существуют и более специализированные IDE, которые могут предложить еще больше удобств.

  • PyCharm (для Python): Разработанная компанией JetBrains, PyCharm — это мощнейшая IDE, созданная специально для Python. Она предлагает превосходное автодополнение кода, глубокую интеграцию с системами контроля версий, удобное управление виртуальными окружениями и мощные инструменты для рефакторинга.46 Существует бесплатная версия (Community) и платная (Professional).
  • Visual Studio (для.NET): Не путать с VS Code. Visual Studio — это полнофункциональная, флагманская IDE от Microsoft для разработки на.NET, доступная для Windows и macOS. Она идеально подходит для создания крупных и сложных приложений, предлагая визуальные дизайнеры, продвинутые инструменты профилирования и глубокую интеграцию со всей экосистемой Microsoft, включая Azure.48

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

Часть 3: Парсинг статических сайтов: основные навыки

Глава 5: Общение с вебом: HTTP-запросы

В основе любого взаимодействия в интернете лежит протокол передачи гипертекста — HTTP (Hypertext Transfer Protocol). Прежде чем мы сможем извлечь данные со страницы, нам нужно ее получить. Этот процесс получения страницы — не что иное, как отправка HTTP-запроса на сервер, где расположен сайт, и получение от него HTTP-ответа.

Основы HTTP для парсера

Представьте общение с веб-сервером как диалог. Вы (клиент) задаете вопрос (отправляете запрос), а сервер дает ответ. В контексте парсинга нас в первую очередь интересуют два типа «вопросов» или, как их называют, HTTP-методов:

  • GET: Самый распространенный метод. Он используется для запроса или «получения» данных с сервера. Когда вы вводите адрес сайта в браузере, он отправляет GET-запрос, чтобы получить HTML-код страницы.49
  • POST: Этот метод используется для отправки данных на сервер. Типичный пример — заполнение и отправка формы входа на сайте или оставление комментария в блоге.49

Каждый раз, когда сервер отвечает, он присылает не только запрошенные данные (например, HTML-код), но и код состояния (status code). Это трехзначное число, которое сообщает, был ли запрос успешным. Для скрейпера важно знать несколько основных кодов 51:

  • 200 OK: Все в порядке. Запрос успешно обработан, и сервер прислал данные.
  • 404 Not Found: Страница не найдена. Вы запросили URL, которого не существует.
  • 403 Forbidden: Доступ запрещен. У вас нет прав для просмотра этой страницы. Иногда сайты используют этот код для блокировки скреперов.
  • 429 Too Many Requests: Слишком много запросов. Вы отправляете запросы слишком часто, и сервер просит вас замедлиться. Это называется ограничением скорости (rate limiting).
  • 5xx Server Error (например, 500, 503): Ошибка на стороне сервера. Проблема не у вас, а на самом сайте.

Подход Python: библиотека requests

В мире Python для работы с HTTP-запросами существует неофициальный стандарт — библиотека requests. Она славится своей простотой и элегантностью, полностью оправдывая один из принципов Python: «Простое лучше, чем сложное».50

Установка:

Bash

pip install requests

Отправка GET-запроса:

Это невероятно просто. Чтобы получить HTML-код страницы, достаточно одной строки:

Python

import requests

url = 'http://quotes.toscrape.com/'
response = requests.get(url)

# Проверяем успешность запроса
if response.status_code == 200:
    # Выводим содержимое страницы
    print(response.text)
else:
    print(f"Ошибка: {response.status_code}")

Объект response содержит всю информацию об ответе сервера. response.status_code хранит код состояния, а response.text — тело ответа (в данном случае, HTML-код) в виде строки.50 Если вы ожидаете данные в формате JSON (например, от API), можно использовать response.json(), который автоматически преобразует ответ в словарь Python.

Передача параметров и заголовков:

Часто требуется передать параметры в URL (например, для поиска ?q=python) или добавить заголовки (headers), чтобы имитировать запрос из реального браузера. requests делает это очень удобным:

Python

import requests

# Параметры для URL
params = {'page': '2'}

# Заголовки, имитирующие браузер
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36'
}

url = 'http://quotes.toscrape.com/'
response = requests.get(url, params=params, headers=headers)

# Итоговый URL будет: http://quotes.toscrape.com/?page=2
print(response.url)
print(response.text)

Библиотека requests автоматически управляет пулом соединений, что позволяет эффективно переиспользовать их для запросов к одному и тому же хосту, повышая производительность.53

Подход.NET: HttpClient и IHttpClientFactory

В.NET для HTTP-запросов используется встроенный класс HttpClient.54 Однако здесь есть важный нюанс, связанный с лучшими практиками.

Как НЕ надо делать:

Наивный подход — создавать новый экземпляр HttpClient для каждого запроса:

C#

// Неправильный подход!
using (var client = new HttpClient())
{
    //... сделать запрос
}

Хотя это кажется логичным из-за using, такой код может привести к серьезной проблеме, называемой «истощением сокетов» (socket exhaustion).54 Каждый новый экземпляр HttpClient резервирует системный сокет, который не освобождается немедленно после использования. При большом количестве запросов это может исчерпать все доступные сокеты и привести к сбоям в приложении.

Как НАДО делать: IHttpClientFactory:

Современный и правильный подход в.NET — использовать IHttpClientFactory. Это фабрика, которая управляет жизненным циклом экземпляров HttpClient централизованно, эффективно переиспользуя их и предотвращая проблему с сокетами.54 Она интегрируется в приложение через механизм внедрения зависимостей (Dependency Injection).

Настройка в консольном приложении.NET:

Сначала установим необходимый пакет:

Bash

dotnet add package Microsoft.Extensions.Http
dotnet add package Microsoft.Extensions.Hosting

Теперь настроим IHttpClientFactory и выполним запрос:

C#using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;

// Создаем хост для использования Dependency Injection
var host = Host.CreateDefaultBuilder(args)
  .ConfigureServices((context, services) =>
    {
        // Регистрируем IHttpClientFactory
        services.AddHttpClient();
    })
  .Build();

// Получаем фабрику из сервис-провайдера
var httpClientFactory = host.Services.GetRequiredService<IHttpClientFactory>();

// Создаем (или получаем из пула) клиент
var client = httpClientFactory.CreateClient();

// Устанавливаем заголовки
client.DefaultRequestHeaders.Add("User-Agent", "My.NET Scraper");

string url = "http://quotes.toscrape.com/";
HttpResponseMessage response = await client.GetAsync(url);

// Проверяем успешность запроса
if (response.IsSuccessStatusCode)
{
    // Читаем содержимое как строку
    string htmlContent = await response.Content.ReadAsStringAsync();
    Console.WriteLine(htmlContent);
}
else
{
    Console.WriteLine($"Ошибка: {response.StatusCode}");
}

Этот подход не только решает проблему с сокетами, но и позволяет централизованно настраивать клиенты (например, задавать базовый адрес или заголовки по умолчанию), что делает код чище и проще в поддержке.55 Освоив отправку HTTP-запросов, вы научились получать «сырой» HTML-код страниц. Следующий шаг — научиться «читать» этот код и извлекать из него ценную информацию.

Глава 6: Парсинг HTML: превращаем веб-страницы в структурированные данные

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

Понимание структуры документа: DOM-дерево

HTML-документ имеет четкую иерархическую структуру, которую удобно представлять в виде дерева — Document Object Model (DOM). Представьте HTML-страницу как генеалогическое древо 60:

  • <html> — это самый главный предок, корень дерева.
  • <head> и <body> — его прямые дети.
  • Теги внутри <body>, например, <h1> и <p>, являются детьми <body>.
  • <head> и <body> — это «братья и сестры» (siblings), так как у них один родитель — <html>.

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

Селекторы: ваш GPS для поиска данных

Чтобы указать парсеру, какой именно элемент на странице нас интересует, мы используем селекторы. Это специальные строки, которые описывают путь к элементу в DOM-дереве. Существует два основных типа селекторов:

  1. CSS-селекторы: Этот синтаксис используется в CSS для стилизации веб-страниц, и он очень удобен и читаем для выбора элементов.
  • p: выбрать все теги <p>.
  • div#main-content: выбрать <div> с id=»main-content».
  • p.article: выбрать все теги <p> с class=»article».
  • ul > li: выбрать все <li>, которые являются прямыми потомками <ul>.
  1. XPath (XML Path Language): Это более мощный и гибкий язык запросов, который позволяет выполнять более сложные выборки.
  • //p: выбрать все теги <p> в документе.
  • //div[@id=’main-content’]: выбрать <div> с атрибутом id равным ‘main-content’.
  • //p[@class=’article’]: выбрать все теги <p> с атрибутом class равным ‘article’.

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

Подход Python: BeautifulSoup и lxml

В Python есть несколько отличных библиотек для парсинга HTML.

BeautifulSoup: Это самая популярная библиотека для начинающих. Она невероятно проста в использовании и очень «терпима» к некорректному или «сломанному» HTML, который часто встречается на реальных сайтах.63

  • Установка: pip install beautifulsoup4 lxml (мы сразу устанавливаем lxml, так как это самый быстрый парсер для BeautifulSoup).
  • Использование:

    Python

    from bs4 import BeautifulSoup
    import requests

    url = 'http://quotes.toscrape.com/'
    response = requests.get(url)
    # Создаем объект Soup, указывая HTML и парсер
    soup = BeautifulSoup(response.text, 'lxml')

    # Находим первый заголовок <h1>
    title = soup.find('h1').text
    print(f"Заголовок страницы: {title}")

    # Используем CSS-селектор для поиска всех цитат
    quotes = soup.select('div.quote')

    for quote in quotes:
      # Внутри каждого блока цитаты ищем текст и автора
      text = quote.select_one('span.text').text
      author = quote.select_one('small.author').text
      print(f"Цитата: {text}\nАвтор: {author}\n")

    soup.find() находит первый тег, soup.find_all() — все теги. Еще более мощные методы — soup.select() и soup.select_one(), которые работают с CSS-селекторами.63 Текст извлекается с помощью .text, а атрибуты — как в словаре, например, link['href'].68

lxml: Это высокопроизводительная библиотека, основанная на C, что делает ее одной из самых быстрых для парсинга XML и HTML.69 Она менее «прощающая», чем BeautifulSoup, но идеально подходит для задач, где важна скорость.

  • Установка: pip install lxml (уже должна быть установлена).
  • Использование: lxml в основном использует XPath для навигации.

    Python

    from lxml import html
    import requests

    url = 'http://quotes.toscrape.com/'
    response = requests.get(url)
    # Создаем дерево из HTML-кода
    tree = html.fromstring(response.content)

    # Используем XPath для поиска всех текстов цитат
    # //div[@class='quote']//span[@class='text']/text()
    # означает: найти все теги <span> с классом 'text' внутри <div> с классом 'quote'
    # и взять их текстовое содержимое.
    texts = tree.xpath("//div[@class='quote']//span[@class='text']/text()")
    authors = tree.xpath("//div[@class='quote']//small[@class='author']/text()")

    for text, author in zip(texts, authors):
      print(f"Цитата: {text}\nАвтор: {author}\n")

Подход.NET: HtmlAgilityPack и AngleSharp

В экосистеме.NET также есть два основных игрока на поле парсинга HTML.

HtmlAgilityPack (HAP): Это ветеран в мире.NET, очень надежная и, как и BeautifulSoup, толерантная к некорректному HTML.72

  • Установка: dotnet add package HtmlAgilityPack.
  • Использование: HAP по умолчанию работает с XPath.

    C#

    using HtmlAgilityPack;
    using System;
    using System.Net.Http;
    using System.Threading.Tasks;

    var url = "http://quotes.toscrape.com/";
    var httpClient = new HttpClient();
    var html = await httpClient.GetStringAsync(url);

    var htmlDocument = new HtmlDocument();
    htmlDocument.LoadHtml(html);

    // Используем XPath для выбора всех блоков с цитатами
    var quoteNodes = htmlDocument.DocumentNode.SelectNodes("//div[@class='quote']");

    if (quoteNodes!= null)
    {
      foreach (var node in quoteNodes)
      {
          var text = node.SelectSingleNode(".//span[@class='text']").InnerText;
          var author = node.SelectSingleNode(".//small[@class='author']").InnerText;
          Console.WriteLine($"Цитата: {text}\nАвтор: {author}\n");
      }
    }


    Для использования CSS-селекторов с HAP необходимо установить дополнительный пакет HtmlAgilityPack.CssSelectors.75

AngleSharp: Это современная, быстрая и строго соответствующая стандартам W3C библиотека. Ее цельпарсить HTML точно так же, как это делает современный браузер.77

  • Установка: dotnet add package AngleSharp.
  • Использование: AngleSharp «из коробки» использует CSS-селекторы, что делает его очень удобным для тех, кто знаком с веб-разработкой.

    C#

    using AngleSharp;
    using System;
    using System.Threading.Tasks;

    // Настраиваем AngleSharp
    var config = Configuration.Default.WithDefaultLoader();
    var context = BrowsingContext.New(config);

    var url = "http://quotes.toscrape.com/";
    // AngleSharp может сам загрузить и распарсить страницу
    var document = await context.OpenAsync(url);

    // Используем CSS-селекторы
    var quoteElements = document.QuerySelectorAll("div.quote");

    foreach (var element in quoteElements)
    {
      var text = element.QuerySelector("span.text").TextContent;
      var author = element.QuerySelector("small.author").TextContent;
      Console.WriteLine($"Цитата: {text}\nАвтор: {author}\n");
    }

Выбор библиотеки зависит от задачи и личных предпочтений. Для новичков в Python BeautifulSoup является отличной отправной точкой. В.NET AngleSharp предлагает более современный и удобный API, основанный на CSS-селекторах.

БиблиотекаЯзыкОсновной селекторСкоростьКлючевая особенность
BeautifulSoupPythonCSS-селекторыСредняяЧрезвычайно дружелюбна к новичкам, отлично справляется с «грязным» HTML.
lxmlPythonXPathОчень высокаяВысокая производительность, может использоваться как парсер для BeautifulSoup.
HtmlAgilityPack.NETXPathВысокаяОчень надежна и толерантна к некорректному HTML, давно существует.
AngleSharp.NETCSS-селекторыОчень высокаяСовременная, строго соответствует стандартам (парсит как браузер).

Выбор инструмента может зависеть от качества целевых сайтов. Для хорошо сформированных, современных сайтов AngleSharp или lxml будут превосходным выбором. Для старых, «сломанных» сайтов HtmlAgilityPack или BeautifulSoup с более снисходительным парсером могут оказаться более щадящими.

Глава 7: Ваш первый полноценный парсер: практический проект

Теория важна, но ничто не закрепляет знания лучше, чем практика. В этой главе мы объединим все, что изучили ранее — HTTP-запросы и HTML-парсинг — чтобы создать наш первый полноценный скрейпер. Мы напишем две версии программы, одну на Python и одну на.NET, которые будут выполнять одну и ту же задачу: собирать все цитаты, имена авторов и теги с главной страницы сайта http://quotes.toscrape.com. Этот сайт специально создан для тренировки навыков парсинга.66

Этот проект продемонстрирует не только синтаксис, но и идиоматические различия в обработке данных между Python и C#. Python естественным образом тяготеет к гибким, динамическим структурам данных, таким как словари, тогда как C# поощряет использование строго типизированных структур, таких как классы или записи. Понимание этого различия поможет вам мыслить в «родном» стиле выбранного языка.

Цель проекта

  1. Текст цитаты.
  2. Имя автора.
  3. Список тегов, связанных с цитатой.
  • Результат: Вывести на экран список собранных данных в структурированном виде.

Шаг 1: Анализ целевой страницы

Прежде чем писать код, откройте сайт в браузере и используйте инструменты разработчика (обычно вызываются клавишей F12 или правым кликом -> «Inspect»/»Исследовать элемент»). Наведите курсор на одну из цитат. Вы увидите, что:

  • Каждая цитата находится внутри тега <div> с классом quote.
  • Текст цитаты находится в <span> с классом text.
  • Имя автора — в <small> с классом author.
  • Теги находятся внутри <div> с классом tags, и каждый тег — это ссылка <a> с классом tag.

Эта структура будет основой для наших селекторов.

Проект на Python (с requests и BeautifulSoup)

1. Настройка проекта:

Создайте папку для проекта, внутри нее — виртуальное окружение и установите необходимые библиотеки:

Bash

mkdir python_scraper
cd python_scraper
python -m venv env
source env/bin/activate  # macOS/Linux
#.\env\Scripts\activate # Windows
pip install requests beautifulsoup4 lxml

Создайте файл scraper.py.

2. Написание кода:

Python

import requests
from bs4 import BeautifulSoup
import json # Для красивого вывода

def scrape_quotes():
    """
    Основная функция для парсинга цитат.
    """
    url = 'http://quotes.toscrape.com/'
   
    try:
        response = requests.get(url)
        # Генерируем исключение, если запрос был неуспешным
        response.raise_for_status()
    except requests.exceptions.RequestException as e:
        print(f"Не удалось получить доступ к странице: {e}")
        return

    soup = BeautifulSoup(response.text, 'lxml')
   
    # Список для хранения всех собранных данных
    all_quotes_data =

    # Находим все контейнеры с цитатами
    quote_containers = soup.select('div.quote')

    for quote in quote_containers:
        # Извлекаем текст цитаты
        text = quote.select_one('span.text').text
       
        # Извлекаем автора
        author = quote.select_one('small.author').text
       
        # Извлекаем теги
        tags_elements = quote.select('a.tag')
        tags = [tag.text for tag in tags_elements]
       
        # Сохраняем данные в словарь
        quote_data = {
            'text': text,
            'author': author,
            'tags': tags
        }
        all_quotes_data.append(quote_data)
       
    return all_quotes_data

if __name__ == '__main__':
    scraped_data = scrape_quotes()
    if scraped_data:
        # Выводим данные в формате JSON для наглядности
        print(json.dumps(scraped_data, indent=4, ensure_ascii=False))

В этом коде мы создаем список словарей (all_quotes_data). Каждый словарь представляет одну цитату и имеет четкие ключи (text, author, tags). Это очень гибкий и типичный для Python подход.

Проект на.NET (с AngleSharp)

1. Настройка проекта:

Откройте терминал, создайте новый проект и установите AngleSharp:

Bash

dotnet new console -n CSharpScraper
cd CSharpScraper
dotnet add package AngleSharp

Откройте проект в VS Code.

2. Написание кода:

Сначала определим класс для хранения наших данных. Это строго типизированный подход, характерный для C#.

Создайте новый файл Quote.cs:

C#

// Quote.cs
using System.Collections.Generic;

public class Quote
{
    public string Text { get; set; }
    public string Author { get; set; }
    public List<string> Tags { get; set; }
}

Теперь изменим основной файл Program.cs:

C#

// Program.cs
using AngleSharp;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text.Json;
using System.Threading.Tasks;

public class Program
{
    public static async Task Main(string args)
    {
        var scrapedData = await ScrapeQuotesAsync();
       
        if (scrapedData.Any())
        {
            // Настраиваем параметры сериализации для красивого вывода
            var options = new JsonSerializerOptions
            {
                WriteIndented = true,
                Encoder = System.Text.Encodings.Web.JavaScriptEncoder.UnsafeRelaxedJsonEscaping
            };
            string jsonString = JsonSerializer.Serialize(scrapedData, options);
            Console.WriteLine(jsonString);
        }
    }

    public static async Task<List<Quote>> ScrapeQuotesAsync()
    {
        var allQuotesData = new List<Quote>();
        var url = "http://quotes.toscrape.com/";

        try
        {
            // Настраиваем AngleSharp для загрузки страницы
            var config = Configuration.Default.WithDefaultLoader();
            var context = BrowsingContext.New(config);
            var document = await context.OpenAsync(url);
           
            // Используем CSS-селекторы для поиска контейнеров с цитатами
            var quoteElements = document.QuerySelectorAll("div.quote");

            foreach (var element in quoteElements)
            {
                var text = element.QuerySelector("span.text")?.TextContent?? "N/A";
                var author = element.QuerySelector("small.author")?.TextContent?? "N/A";
               
                var tags = element.QuerySelectorAll("a.tag")
                                .Select(e => e.TextContent)
                                .ToList();
               
                allQuotesData.Add(new Quote
                {
                    Text = text,
                    Author = author,
                    Tags = tags
                });
            }
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Произошла ошибка: {ex.Message}");
        }

        return allQuotesData;
    }
}

Здесь мы сначала создаем класс Quote, который четко определяет структуру наших данных. Это требует немного больше кода вначале, но обеспечивает безопасность типов и лучшую читаемость в больших проектах. Запустив любой из этих скриптов, вы получите одинаковый по смыслу результат: структурированный список цитат, авторов и тегов, извлеченный с веб-страницы. Вы только что создали свой первый работающий парсер!

Часть 4: Продвинутый парсинг и вызовы современного веба

Глава 8: Масштабируем усилия с помощью Scrapy (Python)

Когда ваш проект по парсингу вырастает за пределы одной-двух страниц, простой скрипт на requests и BeautifulSoup становится громоздким и неэффективным. Нужно обрабатывать постраничную навигацию (пагинацию), управлять потоком данных, сохранять результаты в разные форматы, обрабатывать ошибки. Для таких задач существуют фреймворки — готовые каркасы для приложений, которые берут на себя большую часть рутинной работы.

В мире Python королем фреймворков для парсинга является Scrapy. Это мощный, быстрый и асинхронный фреймворк, созданный специально для написания сложных и производительных краулеров.81

Почему фреймворк? Концепция асинхронности

Главное преимущество Scrapy — его асинхронная природа. Обычный скрипт работает последовательно: отправил запрос -> дождался ответа -> обработал -> отправил следующий запрос. Scrapy же работает как кофейня с несколькими бариста: он может отправить новый запрос, не дожидаясь ответа на предыдущий. Пока один ответ загружается, Scrapy уже работает над другими задачами. Это позволяет выполнять сотни запросов «параллельно», значительно ускоряя процесс сбора данных.82 При этом вам не нужно глубоко вникать в сложности асинхронного программирования на PythonScrapy делает всю магию «под капотом».

Архитектура Scrapy

Scrapy имеет четкую структуру, которая помогает организовать код 83:

  • Spiders (Пауки): Это классы, которые вы пишете. В них определяется логика парсинга: с каких страниц начинать, как переходить по ссылкам и как извлекать данные с каждой страницы.80
  • Items (Элементы): Это структурированные контейнеры для ваших данных, похожие на классы в C#. Они помогают обеспечить консистентность собираемых данных.81
  • Pipelines (Конвейеры): После того как «паук» извлек «элемент» (Item), он отправляется в конвейер. Пайплайны — это классы для постобработки данных: очистка, проверка на дубликаты, сохранение в базу данных или файл.81
  • Settings (Настройки): Центральный файл для конфигурации всего проекта: от задержек между запросами до настроек пайплайнов и User-Agent.81

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

Создание проекта на Scrapy

Давайте перепишем наш парсер цитат с использованием Scrapy, добавив переход по страницам.

1. Установка и создание проекта:

Bash

pip install scrapy
scrapy startproject quotes_project
cd quotes_project

Эта команда создаст папку quotes_project с полной структурой файлов Scrapy.80

2. Создание «паука»:

Перейдите в папку проекта и выполните команду для генерации паука:

Bash

scrapy genspider quotes quotes.toscrape.com

Эта команда создаст файл quotes_project/spiders/quotes.py с шаблоном паука.85

3. Написание логики паука:

Откройте quotes_project/spiders/quotes.py и измените его следующим образом:

Python

import scrapy

class QuotesSpider(scrapy.Spider):
    # Уникальное имя паука
    name = 'quotes'
    # Домен, за пределы которого паук не будет выходить
    allowed_domains = ['quotes.toscrape.com']
    # Стартовый URL
    start_urls = ['http://quotes.toscrape.com/']

    def parse(self, response):
        """
        Этот метод вызывается для каждой загруженной страницы.
        Он извлекает данные и находит ссылку на следующую страницу.
        """
        # Используем CSS-селекторы Scrapy
        for quote in response.css('div.quote'):
            # yield возвращает данные в Scrapy
            yield {
                'text': quote.css('span.text::text').get(),
                'author': quote.css('small.author::text').get(),
                'tags': quote.css('div.tags a.tag::text').getall(),
            }
       
        # Находим ссылку на следующую страницу
        next_page = response.css('li.next a::attr(href)').get()
        if next_page is not None:
            # Если ссылка найдена, создаем новый запрос к ней,
            # используя тот же метод parse для обработки.
            # response.follow автоматически создает полный URL.
            yield response.follow(next_page, callback=self.parse)

Обратите внимание на ключевые отличия от простого скрипта:

  • Мы используем yield вместо return. yield превращает функцию в генератор, который «отдает» данные по одному, не храня все в памяти.
  • Для пагинации мы находим ссылку на следующую страницу и используем response.follow(). Scrapy автоматически поставит этот новый запрос в очередь и обработает его.80

4. Запуск паука и сохранение данных:

Вернитесь в корневую папку проекта (quotes_project) и запустите паука. Scrapy позволяет легко сохранять результаты в разные форматы прямо из командной строки.86

  • Сохранить в JSON:
    Bash
    scrapy crawl quotes -O quotes.json
  • Сохранить в CSV:
    Bash
    scrapy crawl quotes -O quotes.csv

Команда -O перезаписывает файл, а -o — дописывает в конец (для JSON это создаст невалидный файл, поэтому для дозаписи лучше использовать формат JSON Lines с расширением .jl).86

Scrapy — это огромный шаг вперед по сравнению с простыми скриптами. Он предоставляет надежную архитектуру для создания сложных, быстрых и легко поддерживаемых краулеров, которые могут обходить целые сайты, а не только отдельные страницы.

Глава 9: Работа с динамическим вебом с помощью автоматизации браузера

До сих пор мы работали со «статическими» сайтами. Это означает, что весь HTML-контент страницы приходит от сервера в первом же ответе на наш GET-запрос. Однако все больше современных веб-сайтов являются «динамическими». Они используют JavaScript для загрузки данных и построения страницы уже после того, как основной HTML-каркас был получен.

Проблема: контент, генерируемый JavaScript

Когда вы используете requests в Python или HttpClient в.NET, вы получаете только первоначальный HTML. Если важные данные (например, список товаров или комментарии) подгружаются позже с помощью JavaScript, вы их просто не увидите. Ваш парсер получит пустой «скелет» страницы.

Решение: автоматизация браузера и «безголовые» браузеры

Чтобы решить эту проблему, нам нужен инструмент, который умеет выполнять JavaScript так же, как это делает ваш обычный браузер (Chrome, Firefox). Такие инструменты существуют, и они могут управлять настоящим браузером, но без графического интерфейса. Этот режим работы называется «безголовым» (headless).66 Наш код будет программно отдавать команды браузеру: «открой эту страницу», «прокрути вниз», «нажми на эту кнопку», а затем, когда JavaScript отработает и все данные появятся на странице, мы сможем забрать финальный, полностью отрендеренный HTML и отдать его нашему парсеру (BeautifulSoup или AngleSharp).

Два самых популярных инструмента для автоматизации браузера — это Selenium и Playwright.

Selenium: проверенный временем ветеран

Selenium — это мощный фреймворк для автоматизации браузеров, изначально созданный для тестирования веб-приложений, но широко адаптированный для парсинга.87

Настройка:

Для работы с Selenium требуется две вещи: библиотека для вашего языка и специальный драйвер для браузера, которым вы хотите управлять.

  1. Установите библиотеку: pip install selenium.
  2. Скачайте ChromeDriver (https://chromedriver.chromium.org/downloads), убедившись, что его версия соответствует версии вашего браузера Google Chrome.89 Поместите
    chromedriver.exe (или chromedriver для Linux/macOS) в папку с вашим скриптом или в директорию, прописанную в системной переменной PATH.
  1. Установите пакет: dotnet add package Selenium.WebDriver.
  2. Аналогично, скачайте ChromeDriver.88

Пример использования (Python):

Python

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from bs4 import BeautifulSoup
import time

# Указываем путь к драйверу
# Для более новых версий Selenium (4.6+) можно не указывать путь,
# если драйвер в PATH или используется Selenium Manager
driver = webdriver.Chrome()

try:
    # Открываем сайт с динамическим контентом
    driver.get("http://quotes.toscrape.com/js/")

    # Ждем, пока не загрузится хотя бы один блок с цитатой (до 10 секунд)
    # Это критически важный шаг для динамических сайтов!
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located((By.CLASS_NAME, "quote"))
    )

    # Получаем исходный код страницы ПОСЛЕ выполнения JavaScript
    html_content = driver.page_source
   
    # Теперь парсим его с помощью BeautifulSoup
    soup = BeautifulSoup(html_content, 'lxml')
   
    for quote in soup.select('div.quote'):
        print(quote.select_one('span.text').text)

finally:
    # Обязательно закрываем браузер
    driver.quit()

Ключевой момент здесь — WebDriverWait. Мы явно говорим Selenium подождать, пока нужный нам элемент не появится на странице, прежде чем забирать HTML.90

Пример использования (.NET):

C#

using OpenQA.Selenium;
using OpenQA.Selenium.Chrome;
using OpenQA.Selenium.Support.UI;
using System;
using AngleSharp;

// Путь к chromedriver.exe
IWebDriver driver = new ChromeDriver();

try
{
    driver.Navigate().GoToUrl("http://quotes.toscrape.com/js/");

    // Явное ожидание
    var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
    wait.Until(d => d.FindElement(By.ClassName("quote")));

    string htmlContent = driver.PageSource;
   
    // Парсинг с помощью AngleSharp
    var context = BrowsingContext.New(Configuration.Default);
    var document = await context.OpenAsync(req => req.Content(htmlContent));
   
    var quoteElements = document.QuerySelectorAll("div.quote");
    foreach (var element in quoteElements)
    {
        Console.WriteLine(element.QuerySelector("span.text").TextContent);
    }
}
finally
{
    driver.Quit();
}

Playwright: современный и быстрый претендент

Playwright — это более современная библиотека для автоматизации от Microsoft, которая часто оказывается быстрее, надежнее и проще в использовании, чем Selenium.91 Она имеет более современный API и лучше справляется с «капризами» современных веб-приложений.

Настройка:

Установка Playwright проще, так как он сам управляет браузерами.

Пример использования (Python, асинхронный API):

Playwright изначально асинхронен, что делает его очень эффективным.

Python

import asyncio
from playwright.async_api import async_playwright

async def main():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True) # можно headless=False для отладки
        page = await browser.new_page()
       
        await page.goto("http://quotes.toscrape.com/js/")
       
        # Playwright имеет встроенные механизмы ожидания.
        # Метод locator сам подождет появления элемента.
        first_quote = page.locator("div.quote").first
        await first_quote.wait_for()
       
        # Используем встроенные локаторы Playwright для извлечения данных
        all_quotes = await page.locator("div.quote").all()
        for quote in all_quotes:
            text = await quote.locator("span.text").inner_text()
            print(text)
           
        await browser.close()

asyncio.run(main())

Одно из главных преимуществ Playwright — его «автоматические ожидания». Вам не всегда нужно писать явные WebDriverWait, так как многие методы Playwright сами ждут появления элемента перед тем, как с ним взаимодействовать.91

Пример использования (.NET):

C#

using Microsoft.Playwright;
using System;
using System.Threading.Tasks;

class Program
{
    public static async Task Main()
    {
        using var playwright = await Playwright.CreateAsync();
        await using var browser = await playwright.Chromium.LaunchAsync(new() { Headless = true });
        var page = await browser.NewPageAsync();

        await page.GotoAsync("http://quotes.toscrape.com/js/");

        // Локатор сам будет ждать появления элемента
        var firstQuote = page.Locator("div.quote").First;
        await firstQuote.WaitForAsync();

        var allQuotes = await page.Locator("div.quote").AllAsync();
        foreach (var quote in allQuotes)
        {
            var text = await quote.Locator("span.text").InnerTextAsync();
            Console.WriteLine(text);
        }
       
        await browser.CloseAsync();
    }
}

Хотя Selenium является устоявшимся стандартом с огромным количеством документации, для новых проектов стоит рассмотреть Playwright. Он часто предлагает более элегантный и надежный способ решения тех же задач, особенно при работе со сложными одностраничными приложениями (SPA).

Глава 10: Лучшие практики для надежного и уважительного парсинга

Создать парсер, который работает один раз, — это только полдела. Создать скрейпер, который работает надежно, долго и не создает проблем ни вам, ни владельцам сайтов, — вот настоящее мастерство. Веб-сайты активно защищаются от ботов, и это превращается в своего рода «игру в кошки-мышки».75 Чтобы ваш скрейпер не был быстро заблокирован, необходимо следовать ряду лучших практик.

Цель этих практик — не быть агрессивным, а, наоборот, сделать вашего бота как можно более похожим на обычного пользователя. Это стратегия «цифрового камуфляжа»: не пытаться быть невидимым, а слиться с толпой обычного трафика. Использование только одного из этих методов в изоляции часто бывает недостаточно, так как продвинутые системы защиты анализируют совокупность факторов.

1. Ротация прокси-серверов

  • Зачем это нужно? Отправка сотен или тысяч запросов с одного и того же IP-адреса — это самый верный способ привлечь внимание и получить бан. Прокси-сервер — это посредник между вами и целевым сайтом. Ротация прокси означает, что каждый ваш запрос (или каждая группа запросов) отправляется через новый IP-адрес. Для сайта это выглядит так, будто его посещают разные пользователи из разных мест.94
  • Как реализовать (Python requests):
    Самый простой способ — создать список прокси-адресов и случайным образом выбирать один для каждого запроса.

    Python

    import requests
    import random

    # Список ваших прокси-серверов (платные прокси надежнее)
    proxies = [
      'http://user:pass@1.2.3.4:8080',
      'http://user:pass@5.6.7.8:8080',
    ]

    # Выбираем случайный прокси
    proxy = random.choice(proxies)

    response = requests.get(
      'https://httpbin.org/ip', # Этот сайт вернет IP, с которого пришел запрос
      proxies={'http': proxy, 'https': proxy}
    )
    print(response.json())

  • Как реализовать (.NET HttpClient):
    В.NET это настраивается через HttpClientHandler. При использовании IHttpClientFactory можно создать логику, которая будет предоставлять клиенты с разными настройками прокси.

    C#

    using System.Net;
    using System.Net.Http;

    var proxy = new WebProxy
    {
      Address = new Uri("http://1.2.3.4:8080"),
      BypassProxyOnLocal = false,
      UseDefaultCredentials = false,
      // Если прокси требует аутентификации
      Credentials = new NetworkCredential("user", "pass")
    };

    var httpClientHandler = new HttpClientHandler
    {
      Proxy = proxy,
    };

    var client = new HttpClient(handler: httpClientHandler);

    var response = await client.GetAsync("https://httpbin.org/ip");
    var content = await response.Content.ReadAsStringAsync();
    Console.WriteLine(content);


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

2. Ротация User-Agent

  • Зачем это нужно? User-Agent — это HTTP-заголовок, который сообщает сайту, какой браузер и операционная система используются. Библиотеки типа requests или HttpClient по умолчанию отправляют User-Agent, который прямо говорит: «Я — бот» (например, python-requests/2.25.1). Продвинутые сайты могут блокировать запросы с такими заголовками. Ротация User-Agent’ов имитирует запросы от разных браузеров и устройств.98
  • Как реализовать (Python):
    Создайте список реалистичных User-Agent’ов и выбирайте случайный для каждого запроса.

    Python

    import requests
    import random

    user_agents =

    headers = {'User-Agent': random.choice(user_agents)}
    response = requests.get('https://httpbin.org/user-agent', headers=headers)
    print(response.json())


    Для удобства можно использовать библиотеку fake-useragent, которая генерирует актуальные User-Agent’ы.100
  • Как реализовать (.NET):
    Заголовок устанавливается в свойстве DefaultRequestHeaders у HttpClient.
    C#

    //... (код с HttpClient)
    var userAgents = new List<string> { /*... список... */ };
    var random = new Random();
    var userAgent = userAgents[random.Next(userAgents.Count)];

    client.DefaultRequestHeaders.UserAgent.ParseAdd(userAgent);

    var response = await client.GetAsync("https://httpbin.org/user-agent");
    //...

3. Ограничение скорости запросов (Rate Limiting)

  • Зачем это нужно? Боты быстрые, люди — нет. Если ваш скрейпер отправляет запросы с идеальной периодичностью (например, ровно 2 запроса в секунду), он выделяется. Чтобы не перегружать сервер и не получать ошибку 429 Too Many Requests, необходимо искусственно замедлять работу скрейпера, добавляя случайные задержки между запросами.97
  • Как реализовать (Python):
    Самый простой способ — использовать time.sleep() со случайным интервалом.

    Python

    import time
    import random

    for i in range(10):
      #... ваш код для отправки запроса...
      print(f"Сделан запрос номер {i+1}")

      # Пауза от 1 до 3 секунд
      delay = random.uniform(1, 3)
      print(f"Пауза на {delay:.2f} секунд")
      time.sleep(delay)

Для более сложных сценариев существуют библиотеки, такие как requests_ratelimiter, которые могут управлять частотой запросов более гибко.103

  • Как реализовать (.NET):
    Аналогично, используется Task.Delay() со случайным значением.
    C#

    var random = new Random();
    for (int i = 0; i < 10; i++)
    {
      //... ваш код для отправки запроса...
      Console.WriteLine($"Сделан запрос номер {i + 1}");

      // Пауза от 1000 до 3000 миллисекунд
      int delay = random.Next(1000, 3001);
      Console.WriteLine($"Пауза на {delay} мс");
      await Task.Delay(delay);
    }


    В самой платформе ASP.NET Core существуют мощные встроенные механизмы для ограничения скорости входящих запросов, что подчеркивает важность этой концепции в современной веб-разработке.102

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

Часть 5: Управление собранными данными

Глава 11: Хранение ваших данных

Извлечение данных — это только половина дела. Чтобы эти данные принесли пользу, их нужно сохранить в удобном и структурированном формате. Выбор формата хранения зависит от ваших дальнейших целей: хотите ли вы просто просмотреть данные в таблице, использовать их в другом приложении или проводить сложный анализ. Этот выбор лучше делать заранее, чтобы «начинать, имея в виду конечную цель».

Мы рассмотрим три самых распространенных способа хранения: CSV, JSON и база данных SQLite.

Сохранение в CSV (Comma-Separated Values)

CSV — это простой текстовый формат, представляющий собой таблицу, где значения в столбцах разделены запятыми (или другими разделителями, например, точкой с запятой). Файлы CSV легко открываются в любом табличном редакторе, таком как Microsoft Excel или Google Sheets, что делает их идеальными для простого анализа и визуализации.

Подход Python (с библиотекой pandas):

Библиотека pandas — это золотой стандарт для работы с данными в Python. Она предоставляет мощную структуру данных под названием DataFrame, которая очень похожа на таблицу.

  1. Установка: pip install pandas.
  2. Использование: Проще всего сначала собрать все данные в список словарей, а затем преобразовать его в DataFrame и сохранить в CSV.

    Python

    import pandas as pd

    # Предположим, это ваши собранные данные
    scraped_data =},
      {'text': 'It is our choices, Harry...', 'author': 'J.K. Rowling', 'tags': ['abilities', 'choices']}
    ]

    # Создаем DataFrame из списка словарей
    df = pd.DataFrame(scraped_data)

    # Сохраняем в CSV-файл без индекса pandas
    # encoding='utf-8-sig' важен для корректного отображения кириллицы в Excel
    df.to_csv('quotes.csv', index=False, encoding='utf-8-sig')

    print("Данные успешно сохранены в quotes.csv")

  3. Также можно использовать встроенный модуль csv, который не требует установки сторонних библиотек, но работа с ним менее удобна.106

Подход.NET (с библиотекой CsvHelper):

CsvHelper — это популярная и мощная библиотека для работы с CSV в.NET.

  1. Установка: dotnet add package CsvHelper.
  2. Использование: CsvHelper легко записывает список ваших C#-объектов в файл.
    C#

    using CsvHelper;
    using System.Collections.Generic;
    using System.Globalization;
    using System.IO;

    // Предположим, у вас есть класс Quote и список с данными
    // public class Quote { public string Text { get; set; }... }
    var scraped_data = new List<Quote>
    {
      new Quote { Text = "...", Author = "...", Tags = new List<string>{"tag1"} }
    };

    // Записываем данные в файл
    using (var writer = new StreamWriter("quotes.csv"))
    using (var csv = new CsvWriter(writer, CultureInfo.InvariantCulture))
    {
      // CsvHelper автоматически использует публичные свойства объекта как заголовки
      csv.WriteRecords(scraped_data);
    }

    Console.WriteLine("Данные успешно сохранены в quotes.csv");

Сохранение в JSON (JavaScript Object Notation)

JSON — это текстовый формат обмена данными, основанный на парах «ключ-значение». Он очень популярен в веб-приложениях и API, так как легко читается и людьми, и машинами.109 Подход Python (встроенный модуль json):

Python имеет встроенную поддержку JSON.

Python

import json

scraped_data = [
    {'text': '...', 'author': '...', 'tags': ['...']}
]

# Записываем данные в файл
with open('quotes.json', 'w', encoding='utf-8') as f:
    # indent=4 делает файл читаемым для человека
    # ensure_ascii=False для корректного отображения не-ASCII символов
    json.dump(scraped_data, f, indent=4, ensure_ascii=False)

print("Данные успешно сохранены в quotes.json")

Подход.NET (встроенный System.Text.Json):

В современных версиях.NET для работы с JSON используется высокопроизводительная библиотека System.Text.Json.

C#

using System.Collections.Generic;
using System.IO;
using System.Text.Json;
using System.Text.Encodings.Web;

//... список объектов Quote...
var scraped_data = new List<Quote> { /*... */ };

var options = new JsonSerializerOptions
{
    WriteIndented = true, // Для красивого форматирования
    Encoder = JavaScriptEncoder.UnsafeRelaxedJsonEscaping // Для корректной записи символов
};

// Сериализуем список объектов в JSON-строку
string jsonString = JsonSerializer.Serialize(scraped_data, options);

// Записываем строку в файл
File.WriteAllText("quotes.json", jsonString);

Console.WriteLine("Данные успешно сохранены в quotes.json");

Сохранение в базу данных (SQLite)

Когда данных становится много или вы планируете их регулярно обновлять и делать сложные запросы, хранение в файлах становится неэффективным. Здесь на помощь приходят базы данных. SQLite — это легковесная, файловая СУБД, которая не требует отдельного сервера и идеально подходит для небольших и средних проектов.

Подход Python (встроенный модуль sqlite3):

Python поставляется со встроенной поддержкой SQLite.

Python

import sqlite3

scraped_data = [
    {'text': '...', 'author': '...', 'tags': ['change', 'deep-thoughts']}
]

# Подключаемся к файлу БД (он будет создан, если не существует)
conn = sqlite3.connect('quotes.db')
cursor = conn.cursor()

# Создаем таблицу, если ее нет
cursor.execute('''
CREATE TABLE IF NOT EXISTS quotes (
    id INTEGER PRIMARY KEY,
    text TEXT,
    author TEXT,
    tags TEXT
)
''')

# Вставляем данные
for item in scraped_data:
    cursor.execute(
        "INSERT INTO quotes (text, author, tags) VALUES (?,?,?)",
        (item['text'], item['author'], ','.join(item['tags'])) # теги сохраняем как строку
    )

# Сохраняем изменения и закрываем соединение
conn.commit()
conn.close()

print("Данные успешно сохранены в quotes.db");

Подход.NET (с библиотекой Microsoft.Data.Sqlite):

В.NET для работы с базами данных часто используют ORM (Object-Relational Mapper) вроде Entity Framework Core, но для простоты мы воспользуемся более низкоуровневой библиотекой, аналогичной sqlite3 в Python.

  1. Установка: dotnet add package Microsoft.Data.Sqlite.
  2. Использование:

    C#

    using Microsoft.Data.Sqlite;
    using System.Collections.Generic;

    //... список объектов Quote...
    var scraped_data = new List<Quote> { /*... */ };

    using (var connection = new SqliteConnection("Data Source=quotes.db"))
    {
      connection.Open();

      var command = connection.CreateCommand();
      command.CommandText = @"
      CREATE TABLE IF NOT EXISTS quotes (
          id INTEGER PRIMARY KEY,
          text TEXT,
          author TEXT,
          tags TEXT
      );
      ";
      command.ExecuteNonQuery();

      // Вставляем данные
      foreach (var item in scraped_data)
      {
          var insertCmd = connection.CreateCommand();
          insertCmd.CommandText = "INSERT INTO quotes (text, author, tags) VALUES ($text, $author, $tags);";
          insertCmd.Parameters.AddWithValue("$text", item.Text);
          insertCmd.Parameters.AddWithValue("$author", item.Author);
          insertCmd.Parameters.AddWithValue("$tags", string.Join(",", item.Tags));
          insertCmd.ExecuteNonQuery();
      }
    }
    Console.WriteLine("Данные успешно сохранены в quotes.db");

Выбор правильного способа хранения данных — это ключ к их эффективному использованию в будущем.

Глава 12: Заключение и ваш дальнейший путь

Поздравляем! Вы прошли путь от полного новичка до человека, обладающего одним из самых мощных навыков в современном цифровом мире. Вы научились не просто писать код на Python и.NET, но и понимать фундаментальные принципы работы веба, этические и юридические нормы, а также применять передовые инструменты для извлечения, обработки и хранения данных.

Краткое изложение лучших практик

Давайте еще раз закрепим ключевые принципы ответственного парсинга, которые должны стать вашей второй натурой 8:

  1. API — ваш лучший друг: Всегда ищите официальный API перед тем, как начать парсинг. Это самый законный, надежный и эффективный способ получения данных.
  2. Уважайте правила: Внимательно читайте robots.txt и Условия использования (ToS). Не заходите в разделы, которые просят не посещать.
  3. Будьте «легким» гостем: Не перегружайте серверы. Используйте задержки между запросами, ротацию прокси и User-Agent’ов, чтобы ваш скрейпер вел себя как можно более «по-человечески».
  4. Остерегайтесь данных: Будьте предельно осторожны с контентом, защищенным авторским правом, и никогда не собирайте персональные данные без четкого законного основания.

Ваш путь вперед

Освоение парсинга — это не конечная точка, а начало увлекательного путешествия в мир данных. Вот несколько направлений для вашего дальнейшего развития:

  • Практика, практика и еще раз практика: Лучший способ закрепить навыки — это применять их. Найдите проект, который вам интересен. Это может быть что угодно: сбор данных о ваших любимых фильмах, отслеживание цен на товары для хобби, анализ спортивной статистики или сбор открытых данных с правительственных порталов вашего города.
  • Углубление в анализ данных: Собранные данные бесполезны без анализа. Изучите основы анализа данных. Для Python это означает более глубокое погружение в библиотеки pandas, NumPy, а также библиотеки для визуализации, такие как matplotlib и seaborn. В экосистеме.NET вы можете исследовать ML.NET для задач машинного обучения или интегрировать данные с инструментами вроде Power BI.
  • Делитесь с сообществом: Если вы написали полезный скрейпер для открытого источника данных, поделитесь им на GitHub. Если вы собрали и очистили интересный набор данных (который не нарушает никаких правил), опубликуйте его на платформах вроде Kaggle или Datahub.io. Это не только поможет другим, но и станет отличным дополнением к вашему портфолио.20
  • Изучение облачных технологий: Для масштабного и регулярного парсинга научитесь разворачивать свои скреперы в облаке (AWS, Azure, Google Cloud), используя бессерверные функции (Lambda, Azure Functions) или контейнеры (Docker).

Вы получили в свои руки мощный инструмент. Используйте его с умом, ответственностью и любопытством. Веб — это безграничный источник знаний, и теперь у вас есть ключ, чтобы превратить его необработанную информацию в ценные и полезные открытия. Удачи в ваших проектах!

Источники

  1. Web Scraping – что это такое и зачем он нужен — Proxys.io, дата последнего обращения: июля 14, 2025, https://proxys.io/ru/blog/lifehacks/web-scraping
  2. targetinternet.com, дата последнего обращения: июля 14, 2025, https://targetinternet.com/resources/what-is-data-scraping-and-how-can-you-use-it#:~:text=Data%20scraping%2C%20also%20known%20as,that%20data%20to%20another%20website.
  3. Веб-парсинг. Кибрарий – библиотека знаний по кибербезопасности. Всё самое важное и полезное о том, как защитить себя в цифровом мире — Сбербанк, дата последнего обращения: июля 14, 2025, https://www.sberbank.ru/ru/person/kibrary/vocabulary/veb-skraping
  4. Окончательное руководство по веб-парсингу [Обновлено] — RapidSeedbox, дата последнего обращения: июля 14, 2025, https://www.rapidseedbox.com/ru/blog/web-scraping
  5. В чем разница между парсингом и парсингом? — Priceva, дата последнего обращения: июля 14, 2025, https://priceva.ru/blog/article/v-chem-raznitsa-mezhdu-parsingom-i-skrejpingom
  6. Web Scraping | Columbia University Mailman School of Public Health, дата последнего обращения: июля 14, 2025, https://www.publichealth.columbia.edu/research/population-health-methods/web-scraping
  7. Web scraping — Wikipedia, дата последнего обращения: июля 14, 2025, https://en.wikipedia.org/wiki/Web_scraping
  8. Этический веб-парсинг для исследований: принципы и практика — ProxyElite, дата последнего обращения: июля 14, 2025, https://proxyelite.info/ru/web-scraping-for-research-ethical-principles-and-best-practices/
  9. What Is Data Scraping | Techniques, Tools & Mitigation | Imperva, дата последнего обращения: июля 14, 2025, https://www.imperva.com/learn/application-security/data-scraping/
  10. Is Website Scraping Legal? All You Need to Know — GDPR Local, дата последнего обращения: июля 14, 2025, https://gdprlocal.com/is-website-scraping-legal-all-you-need-to-know/
  11. Is web scraping legal? Yes, if you know the rules. — Apify Blog, дата последнего обращения: июля 14, 2025, https://blog.apify.com/is-web-scraping-legal/
  12. Is Web & Data Scraping Legally Allowed? — Zyte, дата последнего обращения: июля 14, 2025, https://www.zyte.com/learn/is-web-scraping-legal/
  13. Законен ли веб-парсинг? Разбираем правовые аспекты | Блог LTESocks, дата последнего обращения: июля 14, 2025, https://ltesocks.io/ru/blog-ru/anonimnost-i-zashhita-informaczii/zakonnost-veb-skrapinga/
  14. О файлах robots.txt | Центр Google Поиска | Documentation, дата последнего обращения: июля 14, 2025, https://developers.google.com/search/docs/crawling-indexing/robots/intro?hl=ru
  15. Инструкция по работе с файлом robots.txt, дата последнего обращения: июля 14, 2025, https://discript.ru/blog/instrukciya-po-rabote-s-fajlom-robots/
  16. Robots.txt for Web Scraping Guide — Bright Data, дата последнего обращения: июля 14, 2025, https://brightdata.com/blog/how-tos/robots-txt-for-web-scraping-guide
  17. How to Read robots.txt for Web Scraping — ZenRows, дата последнего обращения: июля 14, 2025, https://www.zenrows.com/blog/robots-txt-web-scraping
  18. Robots.txt Introduction and Guide | Google Search Central | Documentation, дата последнего обращения: июля 14, 2025, https://developers.google.com/search/docs/crawling-indexing/robots/intro
  19. Всё, что нужно знать о веб-парсинге: законность, этичность и риски — Zennolab Journal, дата последнего обращения: июля 14, 2025, https://journal.zennolab.com/vsjo-chto-nuzhno-znat-o-veb-skrapinge-zakonnost-jetichnost-i-riski/
  20. Ethics & Legality of Webscraping — UCSB Carpentry, дата последнего обращения: июля 14, 2025, https://carpentry.library.ucsb.edu/2022-05-12-ucsb-webscraping/06-Ethics-Legality-Webscraping/index.html
  21. The Legal Landscape of Web Scraping — Quinn Emanuel, дата последнего обращения: июля 14, 2025, https://www.quinnemanuel.com/the-firm/publications/the-legal-landscape-of-web-scraping/
  22. Why do websites have conflicting terms of use and robots.txt? : r/AskComputerScience, дата последнего обращения: июля 14, 2025, https://www.reddit.com/r/AskComputerScience/comments/17k8wgo/why_do_websites_have_conflicting_terms_of_use_and/
  23. Законность и Этика Веб-Парсинга в России — Школа Виктора Комлева, дата последнего обращения: июля 14, 2025, https://victor-komlev.ru/zakonnost-i-etika-veb-skrejpinga/
  24. Парсинг сайтов — законно ли? — Веб-студия Яворского, дата последнего обращения: июля 14, 2025, https://yavorsky.ru/stati/parsingsaitovzakonno/
  25. Парсинг данных в России: этические аспекты и законодательство, дата последнего обращения: июля 14, 2025, https://dataparsing.pro/dataparsing-blog/parsing-dannyh-v-rossii-eticheskie-aspekty-i-zakonodatelstvo/
  26. Web-scraping and copyright law — Neudata, дата последнего обращения: июля 14, 2025, https://www.neudata.co/blog/web-scraping-and-copyright-law
  27. Парсинг: законно ли им пользоваться — Altcraft CDP, дата последнего обращения: июля 14, 2025, https://altcraft.com/ru/glossary/parsing-chto-eto-takoe-i-mogut-li-za-nego-oshtrafovat
  28. How to Comply with the GDPR and CCPA as a Web Scraper — McCarthy Law Group, дата последнего обращения: июля 14, 2025, https://mccarthylg.com/how-to-comply-with-the-gdpr-and-ccpa-as-a-web-scraper/
  29. gdprlocal.com, дата последнего обращения: июля 14, 2025, https://gdprlocal.com/is-website-scraping-legal-all-you-need-to-know/#:~:text=Ethical%20scrapers%20should%20avoid%20collecting,standards%20and%20avoid%20legal%20repercussions.
  30. Understanding the Legal Landscape of Web Scraping — InstantAPI.ai, дата последнего обращения: июля 14, 2025, https://web.instantapi.ai/blog/understanding-the-legal-landscape-of-web-scraping/
  31. Ethics & Legality of Web Scraping — UCSB Carpentry, дата последнего обращения: июля 14, 2025, https://carpentry.library.ucsb.edu/2024-02-27-ucsb-webscraping/04-Ethics-Legality-Webscraping/index.html
  32. Legal and Ethical Considerations — Python Web Scraping — Monash Data Fluency, дата последнего обращения: июля 14, 2025, https://monashdatafluency.github.io/python-web-scraping/section-5-legal-and-ethical-considerations/
  33. How To Install Python on Windows, macOS, and Linux — Kinsta®, дата последнего обращения: июля 14, 2025, https://kinsta.com/knowledgebase/install-python/
  34. Как установить Python на Windows, macOS и Linux — Хекслет, дата последнего обращения: июля 14, 2025, https://kz.hexlet.io/blog/posts/kak-ustanovit-python-na-windows-macos-i-linux
  35. Visual Studio Code: установка и настройка для Python — Timeweb Cloud, дата последнего обращения: июля 14, 2025, https://timeweb.cloud/tutorials/code-editor/visual-studio-code-ustanovka-i-nastrojka-dlya-python
  36. How to Install Pip on Mac {3 Methods} | phoenixNAP KB, дата последнего обращения: июля 14, 2025, https://phoenixnap.com/kb/install-pip-mac
  37. How to Install Python and Pip on Windows, Linux, and macOS — Codevisionz, дата последнего обращения: июля 14, 2025, https://codevisionz.com/lessons/how-to-install-pip-on-windows-linux-and-macos/
  38. Как установить PIP для Python на Windows, Мас и Linux — PythonRu, дата последнего обращения: июля 14, 2025, https://pythonru.com/baza-znanij/ustanovka-pip-dlja-python-i-bazovye-komandy
  39. Installing Packages — Python Packaging User Guide, дата последнего обращения: июля 14, 2025, https://packaging.python.org/tutorials/installing-packages/
  40. How to Install .NET on Linux and macOS — Engine Designs, дата последнего обращения: июля 14, 2025, https://enginedesigns.net/post/2021/01/how_to_install_dotnet_on_linux_and_macos/
  41. How to install .NET Core on Windows, Linux, and macOS | by Emma White | Medium, дата последнего обращения: июля 14, 2025, https://emma-white20.medium.com/how-to-install-net-core-on-windows-linux-and-macos-ad709432c1ca
  42. Как правильно настроить Visual Studio Code для работы с Python? — External Software, дата последнего обращения: июля 14, 2025, https://external.software/archives/13769
  43. VS Code — настройка и использование для Python-кода, дата последнего обращения: июля 14, 2025, https://pythonchik.ru/osnovy/python-i-vs-code
  44. Quick Start Guide for Python in VS Code, дата последнего обращения: июля 14, 2025, https://code.visualstudio.com/docs/python/python-quick-start
  45. Getting Started with Python in VS Code, дата последнего обращения: июля 14, 2025, https://code.visualstudio.com/docs/python/python-tutorial
  46. PyCharm: как установить и использовать для Python – GoIT Global, дата последнего обращения: июля 14, 2025, https://goit.global/ua-ru/articles/pycharm-kak-ustanovyt-y-yspolzovat-dlia-python/
  47. Эффективная разработка на Python с PyCharm: советы и трюки — Хекслет, дата последнего обращения: июля 14, 2025, https://ru.hexlet.io/blog/posts/effektivnaya-razrabotka-na-python-s-pycharm-sovety-i-tryuki
  48. Начните работу с ASP.NET Core MVC — Learn Microsoft, дата последнего обращения: июля 14, 2025, https://learn.microsoft.com/ru-ru/aspnet/core/tutorials/first-mvc-app/start-mvc?view=aspnetcore-9.0
  49. Как работать с командами get/post — Otus, дата последнего обращения: июля 14, 2025, https://otus.ru/journal/kak-rabotat-s-komandami-html-get-post/
  50. Python requests Library: How to Make HTTP Requests with Python — Mimo, дата последнего обращения: июля 14, 2025, https://mimo.org/glossary/python/requests-library
  51. Python Requests Library: 2025 Guide — Oxylabs, дата последнего обращения: июля 14, 2025, https://oxylabs.io/blog/python-requests
  52. Requests — PyPI, дата последнего обращения: июля 14, 2025, https://pypi.org/project/requests/
  53. Requests: HTTP for Humans™ — Requests 2.32.4 documentation, дата последнего обращения: июля 14, 2025, https://requests.readthedocs.io/
  54. ASP.NET Core HttpClient Tutorial — Julio Casal, дата последнего обращения: июля 14, 2025, https://juliocasal.com/blog/ASP.NET-Core-HttpClient-Tutorial
  55. HTTP Requests in .NET Core with HttpClient and HttpClientFactory — C# Corner, дата последнего обращения: июля 14, 2025, https://www.c-sharpcorner.com/article/http-requests-in-net-core-with-httpclient-and-httpclientfactory/
  56. Make HTTP requests with the HttpClient — .NET — Learn Microsoft, дата последнего обращения: июля 14, 2025,
  57. Using HttpClient — The Right Way — C# Corner, дата последнего обращения: июля 14, 2025, https://www.c-sharpcorner.com/blogs/use-httpclient-in-the-right-way
  58. HTTP Client in C#: Best Practices for Experts | by iamprovidence | Medium, дата последнего обращения: июля 14, 2025, https://medium.com/@iamprovidence/http-client-in-c-best-practices-for-experts-840b36d8f8c4
  59. HttpClient with ASP.NET Core Tutorial — Code Maze, дата последнего обращения: июля 14, 2025, https://code-maze.com/httpclient-with-asp-net-core-tutorial/
  60. Tutorial: Web Scraping with Python Using Beautiful Soup — Dataquest, дата последнего обращения: июля 14, 2025, https://www.dataquest.io/blog/web-scraping-tutorial-python/
  61. Beautiful Soup Quick Guide — Tutorialspoint, дата последнего обращения: июля 14, 2025, https://www.tutorialspoint.com/beautiful_soup/beautiful_soup_quick_guide.htm
  62. How to use HTML Agility Pack ? — GeeksforGeeks, дата последнего обращения: июля 14, 2025, https://www.geeksforgeeks.org/html/how-to-use-html-agility-pack/
  63. Beautiful Soup Tutorial — Tutorialspoint, дата последнего обращения: июля 14, 2025, https://www.tutorialspoint.com/beautiful_soup/index.htm
  64. A guide to web scraping in Python using Beautiful Soup — Opensource.com, дата последнего обращения: июля 14, 2025, https://opensource.com/article/21/9/web-scraping-python-beautiful-soup
  65. Beautiful Soup Documentation, дата последнего обращения: июля 14, 2025, https://sethc23.github.io/wiki/Python/Beautiful_Soup_Documentation.pdf
  66. BeautifulSoup Web Scraping: Step-By-Step Tutorial — Bright Data, дата последнего обращения: июля 14, 2025, https://brightdata.com/blog/how-tos/beautiful-soup-web-scraping
  67. BeautifulSoup tutorial: Scraping web pages with Python | ScrapingBee, дата последнего обращения: июля 14, 2025, https://www.scrapingbee.com/blog/python-web-scraping-beautiful-soup/
  68. Beautiful Soup: Build a Web Scraper With Python, дата последнего обращения: июля 14, 2025, https://realpython.com/beautiful-soup-web-scraper-python/
  69. oxylabs/lxml-tutorial: A tutorial on parsing webpages with lxmlGitHub, дата последнего обращения: июля 14, 2025, https://github.com/oxylabs/lxml-tutorial
  70. lxml Tutorial: XML Processing and Web Scraping With lxml — Oxylabs, дата последнего обращения: июля 14, 2025, https://oxylabs.io/blog/lxml-tutorial
  71. lxml — Dataforest, дата последнего обращения: июля 14, 2025, https://dataforest.ai/glossary/lxml
  72. Html Agility Pack, дата последнего обращения: июля 14, 2025, https://html-agility-pack.net/
  73. Getting Started With HTML Agility Pack — C# Corner, дата последнего обращения: июля 14, 2025, https://www.c-sharpcorner.com/UploadFile/9b86d4/getting-started-with-html-agility-pack/
  74. zzzprojects/html-agility-pack — GitHub, дата последнего обращения: июля 14, 2025, https://github.com/zzzprojects/html-agility-pack
  75. HTML Agility Pack: How to Parse Data (Tutorial 2025) — ZenRows, дата последнего обращения: июля 14, 2025, https://www.zenrows.com/blog/html-agility-pack
  76. Parsing websites in C# with Html Agility Pack or AngleSharp — elmah.io Blog, дата последнего обращения: июля 14, 2025, https://blog.elmah.io/parsing-websites-in-c-with-html-agility-pack-or-anglesharp/
  77. AngleSharp — CodeProject, дата последнего обращения: июля 14, 2025, https://www.codeproject.com/Articles/609053/AngleSharp
  78. AngleSharp/docs/general/01-Basics.md at devel — GitHub, дата последнего обращения: июля 14, 2025, https://github.com/AngleSharp/AngleSharp/blob/devel/docs/general/01-Basics.md
  79. Parsing HTML With AngleSharp in C# — Code Maze, дата последнего обращения: июля 14, 2025, https://code-maze.com/csharp-parsing-html-with-anglesharp/
  80. Scrapy Tutorial — Scrapy 2.13.3 documentation, дата последнего обращения: июля 14, 2025, https://docs.scrapy.org/en/latest/intro/tutorial.html
  81. Scrapy Tutorial — Tutorialspoint, дата последнего обращения: июля 14, 2025, https://www.tutorialspoint.com/scrapy/index.htm
  82. Web Scraping With Scrapy: The Complete Guide in 2025 — Scrapfly, дата последнего обращения: июля 14, 2025, https://scrapfly.io/blog/posts/web-scraping-with-scrapy
  83. Python Tutorial: Web Scraping with Scrapy (8 Code Examples) — Dataquest, дата последнего обращения: июля 14, 2025, https://www.dataquest.io/blog/web-scraping-with-scrapy/
  84. Scrapy in Python: Web Scraping Tutorial 2025 — ZenRows, дата последнего обращения: июля 14, 2025, https://www.zenrows.com/blog/scrapy-python
  85. Web Scraping with Scrapy: Python Tutorial — Oxylabs, дата последнего обращения: июля 14, 2025, https://oxylabs.io/blog/scrapy-web-scraping-tutorial
  86. Writing Scrapy Python Output to JSON file — GeeksforGeeks, дата последнего обращения: июля 14, 2025, https://www.geeksforgeeks.org/python/writing-scrapy-python-output-to-json-file/
  87. Python Web Scraping Tutorials, дата последнего обращения: июля 14, 2025, https://realpython.com/tutorials/web-scraping/
  88. How to perform Web Scraping using Selenium C# | BrowserStack, дата последнего обращения: июля 14, 2025, https://www.browserstack.com/guide/web-scraping-using-selenium-c-sharp
  89. Selenium Web Scraping: A Tutorial — Built In, дата последнего обращения: июля 14, 2025, https://builtin.com/articles/selenium-web-scraping
  90. Web Scraping with Selenium: Step-by-Step Tutorial — ScraperAPI, дата последнего обращения: июля 14, 2025, https://www.scraperapi.com/web-scraping/selenium/
  91. Playwright Web Scraping Tutorial for 2025 — Oxylabs, дата последнего обращения: июля 14, 2025, https://oxylabs.io/blog/playwright-web-scraping
  92. Playwright Web Scraping: A Practical Tutorial — Smartproxy, дата последнего обращения: июля 14, 2025, https://smartproxy.com/blog/playwright-web-scraping
  93. Playwright in C# for Web Scraping: Step-by-Step Tutorial — ZenRows, дата последнего обращения: июля 14, 2025, https://www.zenrows.com/blog/playwright-c-sharp
  94. How to Rotate Proxies in Python — ZenRows, дата последнего обращения: июля 14, 2025, https://www.zenrows.com/blog/rotate-proxies-python
  95. How to Rotate Proxies in Python Using Requests and AIOHTTP — Oxylabs, дата последнего обращения: июля 14, 2025, https://oxylabs.io/blog/rotate-proxies-python
  96. Boost Web Scraping: Rotating Proxy Networks & IP Rotation — Evomi Blog, дата последнего обращения: июля 14, 2025, https://evomi.com/blog/boost-web-scraping-rotating-proxies
  97. Rate Limit in Web Scraping: How It Works and 5 Bypass Methods, дата последнего обращения: июля 14, 2025, https://scrape.do/blog/web-scraping-rate-limit/
  98. How to Implement User Agent Rotation for Web Scraping — Blog | WebScraping.AI, дата последнего обращения: июля 14, 2025, https://webscraping.ai/blog/user-agent-rotation-for-web-scraping
  99. HttpClient User Agent in C#: How to Set It — ZenRows, дата последнего обращения: июля 14, 2025, https://www.zenrows.com/blog/c-sharp-httpclient-user-agent
  100. Changing User Agent in Python Requests for Effective Web Scraping — ScrapingAnt, дата последнего обращения: июля 14, 2025, https://scrapingant.com/blog/change-user-agent-python-requests
  101. Dealing with Rate Limiting and Throttling — UseScraper, дата последнего обращения: июля 14, 2025, https://usescraper.com/blog/dealing-with-rate-limiting-and-throttling
  102. Rate limiting middleware in ASP.NET Core — Learn Microsoft, дата последнего обращения: июля 14, 2025, https://learn.microsoft.com/en-us/aspnet/core/performance/rate-limit?view=aspnetcore-9.0
  103. Python Request Optimization: Caching and Rate Limiting | by PI | Neural Engineer | Medium, дата последнего обращения: июля 14, 2025, https://medium.com/neural-engineer/python-request-optimization-caching-and-rate-limiting-79ceb5e6eb1e
  104. Rate Limiting in Web API’s in .NET 8 | CodeNx — Medium, дата последнего обращения: июля 14, 2025, https://medium.com/codenx/rate-limiting-in-web-apis-in-net-8-1378f3207d87
  105. Saving a Pandas Dataframe as a CSV — GeeksforGeeks, дата последнего обращения: июля 14, 2025, https://www.geeksforgeeks.org/pandas/saving-a-pandas-dataframe-as-a-csv/
  106. How to save the result of scraping in a CSV? — Stack Overflow, дата последнего обращения: июля 14, 2025, https://stackoverflow.com/questions/69030056/how-to-save-the-result-of-scraping-in-a-csv
  107. Getting Started | CsvHelper, дата последнего обращения: июля 14, 2025, https://joshclose.github.io/CsvHelper/getting-started/
  108. Examples | CsvHelper, дата последнего обращения: июля 14, 2025, https://joshclose.github.io/CsvHelper/examples/
  109. JSON и XML – разница между представлениями данных — AWSAmazon.com, дата последнего обращения: июля 14, 2025, https://aws.amazon.com/ru/compare/the-difference-between-json-xml/
  110. Глава 3: Типы и форматы API / Хабр — Habr, дата последнего обращения: июля 14, 2025, https://habr.com/ru/articles/891358/
  111. How to Store Scraped Web Data in Python Using JSON Dumps — Rayobyte, дата последнего обращения: июля 14, 2025, https://rayobyte.com/blog/how-to-use-json-dumps-in-python/
  112. Saving Scraped Data To SQLite Database With Scrapy Pipelines — ScrapeOps, дата последнего обращения: июля 14, 2025, https://scrapeops.io/python-scrapy-playbook/scrapy-save-data-sqlite/
Администратор

Recent Posts

Парсинг контактов клиентов с сайтов ваших конкурентов

Краткое саммари: опасная иллюзия легких лидов В мире жесткой конкуренции идея быстро пополнить клиентскую базу,…

1 день ago

Сеть сайтов под РСЯ: пошаговое руководство по созданию

Краткое резюме: как превратить сеть сайтов в стабильный источник дохода Создание сети информационных сайтов —…

1 неделя ago

Полное руководство по бесплатным SEO-сервисам для аудита и устранения ошибок сайта

Знаете ли вы, что невидимые технические ошибки могут «съедать» до 90% вашего потенциального трафика из…

2 недели ago

Парсинг цен конкурентов: полное руководство по обходу блокировок и защит

Введение: почему мониторинг цен — необходимость, а защита — не преграда Представьте, что вы пытаетесь…

2 недели ago

Полное руководство по защите сайта от ботов: стратегии, технологии и правовые аспекты в России

Значительная часть трафика на любом коммерческом сайте — это не люди. Это боты, которые могут…

2 недели ago

Мониторинг цен конкурентов: полное руководство по парсингу, праву и стратегиям для бизнеса

Систематический мониторинг цен конкурентов — это не просто способ избежать ценовых войн, а доказанный инструмент…

2 недели ago