Руководство по веб-скрапингу на Python для начинающих

Комментарии: 0

Python является одним из самых популярных языков программирования для веб-скрапинга благодаря своим мощным библиотекам и интуитивно понятному синтаксису. В этой статье будут рассмотрены основы веб-скрапинга и настройка среды для разработки первого веб-скрапера на Python с помощью библиотек Beautiful Soup, Playwright и lxml.

Библиотеки Python для веб-скрапинга

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

  • Requests: используется для отправки HTTP-запросов. Она позволяет парсить веб-страницы и взаимодействовать с ними.
  • Beautiful Soup: подходит для парсинга HTML и XML документов. Она создает структуры из исходного кода страницы, упрощая процесс извлечения данных.
  • lxml: особенно хорошо подходит для разбора XML и HTML документов и часто используется в проектах, требующих быстрой обработки данных.
  • Playwright: мощный инструмент для скрапинга динамических веб-страниц. Он позволяет не только извлекать данные, но и взаимодействовать с элементами на странице, поддерживая автоматизацию браузера на уровне API.

Что такое HTTP-запросы

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

Настройка среды

Первый шаг — установка Python. Скачать Python для последующей установки в системе можно с официального сайта.

Второй шаг — настройка виртуальной среды для управления зависимостями. Для создания и активации виртуальной среды используются следующие команды:


python -m venv scraping_env
source scraping_env/bin/activate

Далее необходимо установить пакеты с помощью следующих команд:


pip install requests
pip install beautifulsoup4 
pip install lxml

Создание веб-скрапера с использованием Beautiful Soup

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

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

Самый распространенный тип HTTP-запроса — GET-запрос, который используется для получения данных с указанного URL. Вот базовый пример того, как выполнить GET-запрос на http://example.com:


import requests
url = 'http://example.com'
response = requests.get(url)

Обработка HTTP-ответов

Библиотека requests предоставляет несколько способов обработки и обработки ответа:

Проверка статуса кода: убедитесь, что запрос был успешным.


if response.status_code == 200:
    print('Request was successful!')
else:
    print('Request failed with status code:', response.status_code)

Извлечение содержимого: извлеките текст или содержимое в формате JSON из ответа.


# Получение содержимого ответа в виде текста
page_content = response.text
print(page_content)

# Получение содержимого ответа в формате JSON (если ответ в формате JSON)
json_content = response.json()
print(json_content)

Обработка и сетевых и HTTP ошибок

При веб-скрапинге есть риск столкнуться с различными сетевыми и HTTP ошибками. Например, ресурс может быть временно недоступен, запрос может превышать установленное время ожидания, или сервер может возвращать ошибочные HTTP статусы, такие как 404 (Not Found) или 500 (Internal Server Error). Эти ситуации могут нарушить нормальное выполнение скрипта, если они не будут должным образом обработаны.


import requests

url = 'http://example.com'

try:
    response = requests.get(url, timeout=10)  # Установка таймаута для запроса
    response.raise_for_status()  # Вызов ошибки HTTP Error для некорректных ответов
except requests.exceptions.HTTPError as http_err:
    print(f'HTTP error occurred: {http_err}')
except requests.exceptions.ConnectionError:
    print('Failed to connect to the server.')
except requests.exceptions.Timeout:
    print('The request timed out.')
except requests.exceptions.RequestException as req_err:
    print(f'Request error: {req_err}')
else:
    print('Request was successful!')

Извлечение данных из HTML-элементов

В этой части мы рассмотрим, как можно определить и извлечь данные из HTML-элементов, используя популярные библиотеки, такие как Beautiful Soup и lxml.

HTML (HyperText Markup Language) — это основной язык разметки для создания веб-страниц. Он использует вложенные элементы, представленные тегами, такими как <div>, <p>, <a>, и другие. Каждый тег может содержать текст, другие теги или оба этих элемента, а также различные атрибуты, которые могут предоставлять дополнительную информацию о теге.

XPath и CSS-селекторы — два инструмента, которые предоставляют универсальные способы для выбора элементов на основе их атрибутов или позиции в документе.

Обнаружение XPath и CSS селекторов

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

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

  1. Открытие инструментов разработчика:
    • В Chrome: Щелкните правой кнопкой мыши на странице и выберите “Inspect” или нажмите Ctrl+Shift+I (Windows/Linux) или Cmd+Opt+I (Mac).
    • В Firefox: Щелкните правой кнопкой мыши на странице и выберите “Inspect Element” или нажмите Ctrl+Shift+I (Windows/Linux) или Cmd+Opt+I (Mac).
  2. Исследование элемента:
    • Используйте инструмент для инспекции (иконка курсора) для наведения и клика по элементу, данные с которого вы хотите извлечь. Это выделит элемент в DOM-структуре страницы.
  3. Копирование XPath или CSS селектора:
    • Щелкните правой кнопкой мыши по выделенному HTML элементу в панели инструментов разработчика.
    • Выберите “Copy”, а затем выберите “Copy XPath” для копирования XPath пути элемента или “Copy selector” для копирования CSS селектора.

1n.png

XPath: /html/body/div/h1

CSS Selector: body > div > h1

Извлечение данных с использованием Beautiful Soup

Beautiful Soup — библиотека Python для парсинга HTML и XML документов. Она предоставляет простые методы и атрибуты для навигации и поиска по структуре HTML.


from bs4 import BeautifulSoup
import requests

# URL веб-страницы для скрапинга
url = 'https://example.com'

# Отправка HTTP GET запроса на URL
response = requests.get(url)

# Парсинг HTML содержимого ответа с помощью Beautiful Soup
soup = BeautifulSoup(response.content, 'html.parser')

# Использование CSS селектора для поиска всех тегов <h1>, которые находятся внутри тегов <div>,
# являющихся прямыми предшественниками тега <body>
h1_tags = soup.select('body > div > h1')

# Итерация по списку найденных тегов <h1> и вывод их текстового содержимого
for tag in h1_tags:
    print(tag.text)

Устранение ошибок парсинга

Ошибки парсинга часто возникают, когда структура HTML или XML страницы отличается от ожидаемой, что может привести к проблемам при извлечении данных. Один из наиболее частых типов исключений, который может возникнуть при работе с библиотеками, такими как Beautiful Soup, — AttributeError.


from bs4 import BeautifulSoup
import requests

# URL веб-страницы для скрапинга
url = 'https://example.com'

# Отправка HTTP GET запроса на URL
response = requests.get(url)

try:
    # Парсинг HTML содержимого ответа с помощью Beautiful Soup
    soup = BeautifulSoup(response.content, 'html.parser')

   # Использование CSS селектора для поиска всех тегов <h1>, которые находятся внутри тегов <div>,
# являющихся прямыми предшественниками тега <body>
    h1_tags = soup.select('body > div > h1')

      # Итерация по списку найденных тегов <h1> и вывод их текстового содержимого
    for tag in h1_tags:
        print(tag.text)
except AttributeError as attr_err:
   # Обработка случаев, когда может возникнуть AttributeError (например, если response.content равен None)
    print(f'Attribute error occurred: {attr_err}')
except Exception as parse_err:
    # Обработка любых других исключений, которые могут возникнуть во время парсинга
    print(f'Error while parsing HTML: {parse_err}')

Извлечение данных с использованием lxml

lxml предлагает более глубокий уровень контроля и оптимизации, что делает библиотеку отличным выбором для обработки больших объемов данных или особенно сложных XML/HTML структур.


from lxml.html import fromstring
import requests

# URL веб-страницы для скрапинга
url = 'https://example.com'

# Отправка HTTP GET запроса на URL
response = requests.get(url)

# Парсинг HTML содержимого ответа с использованием метода fromstring библиотеки lxml
parser = fromstring(response.text)

# Использование XPath для поиска всех тегов <h1>, которые находятся внутри тегов <div>,
# являющихся прямыми предшественниками тега <body>

title = parser.xpath('/html/body/div/h1/text()')[0]

# Вывод заголовка
print(title)

Обработка ошибок парсинга

Как и Beautiful Soup, библиотека lxml позволяет обрабатывать ошибки парсинга, включая исключения, такие как lxml.etree.XMLSyntaxError, возникающие при наличии синтаксических ошибок в HTML или XML документах.


from lxml.html import fromstring
from lxml import etree
import requests

# URL веб-страницы для скрейпинга
url = 'https://example.com'

# Отправка HTTP GET запроса на URL
response = requests.get(url)

try:
    # Парсинг HTML содержимого ответа с использованием метода fromstring библиотеки lxml
    parser = fromstring(response.text)

    # Использование CSS селектора для поиска всех тегов <h1>, которые находятся внутри тегов <div>,
# являющихся прямыми предшественниками тега <body>

    title = parser.xpath('/html/body/div/h1/text()')[0]

    # Вывод заголовка
    print(title)
except IndexError:
    # Обработка случая, когда XPath запрос не возвращает результатов
    print('No <h1> tag found in the specified location.')
except etree.XMLSyntaxError as parse_err:
    # Обработка ошибок синтаксиса XML при парсинге
    print(f'Error while parsing HTML: {parse_err}')
except Exception as e:
    # Обработка любых других исключений
    print(f'An unexpected error occurred: {e}')

Сохранение извлеченных данных

Следующий важный шаг после успешного извлечения данных из HTML-элементов — их сохранение. Python предоставляет множество опций для выполнения этой задачи, включая форматы файлов, такие как CSV и JSON.

Сохранение данных в файл CSV

CSV (Comma-Separated Values) — простой и широко используемый формат для хранения табличных данных. Модуль csv в Python предоставляет удобные инструменты для записи данных в файлы CSV.


import csv

# Пример данных
data = {
    'title': 'Example Title',
    'paragraphs': ['Paragraph 1', 'Paragraph 2', 'Paragraph 3']
}

# Сохранение данных в файл CSV
with open('scraped_data.csv', mode='w', newline='', encoding='utf-8') as file:
    writer = csv.writer(file)
    writer.writerow(['Title', 'Paragraph'])
    for paragraph in data['paragraphs']:
        writer.writerow([data['title'], paragraph])

print('Data saved to scraped_data.csv')

Сохранение данных в файл JSON

JSON (JavaScript Object Notation) — популярный и легкий формат обмена данными, хорошо подходящий для хранения структурированной информации. Благодаря своей структуре, JSON идеально подходит для хранения данных в виде объектов или массивов, что делает его особенно полезным для веб-скрапинга.


import json

# Пример данных
data = {
    'title': 'Example Title',
    'paragraphs': ['Paragraph 1', 'Paragraph 2', 'Paragraph 3']
}

# Сохранение данных в файл JSON
with open('scraped_data.json', mode='w', encoding='utf-8') as file:
    json.dump(data, file, ensure_ascii=False, indent=4)

print('Data saved to scraped_data.json')

Продвинутые техники веб-скрапинга при помощи Playwright

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

Для установки Playwright и его настройки выполните следующие команды:


pip install playwright
playwright install

Скрапинг динамического контента

Playwright позволяет взаимодействовать с веб-элементами, такими как заполнение форм и нажатие кнопок. Он может ожидать завершения AJAX-запросов перед продолжением, что делает его идеальным для скрапинга динамического контента. Приведенный код демонстрирует скрапинг страницы продукта на Amazon с использованием Playwright и lxml.

2n.png

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

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

HTML-содержимое затем анализируется с использованием метода fromstring библиотеки lxml для создания дерева элементов. С помощью XPath-запроса извлекается текстовое содержимое названия продукта из определенного элемента <span> с ID productTitle. Скрипт включает обработку ошибок для управления случаями, когда XPath-запрос не возвращает результатов, возникают синтаксические ошибки XML при парсинге или любые другие неожиданные исключения. Наконец, выводится извлеченное название продукта, и контекст браузера и сам браузер закрываются для завершения сеанса.

Функция run выполняется в сеансе Playwright, начатом с помощью sync_playwright, что обеспечивает управление и выполнение всего процесса в контролируемой среде. Эта структура обеспечивает надежность и устойчивость к ошибкам во время выполнения задачи веб-скрапинга.


from playwright.sync_api import Playwright, sync_playwright
from lxml.html import fromstring, etree


def run(playwright: Playwright) -> None:
   # Определение прокси-сервера
   proxy = {"server": "https://IP:PORT", "username": "LOGIN", "password": "PASSWORD"}

   # Запуск нового экземпляра браузера с указанным прокси и в режиме без интерфейса
   browser = playwright.chromium.launch(
       headless=False,
       proxy=proxy,
       slow_mo=50,
       args=['--ignore-certificate-errors'],
   )

   # Создание нового контекста браузера
   context = browser.new_context(ignore_https_errors=True)

   # Открытие новой страницы в контексте браузера
   page = context.new_page()

   # Переход на указанную страницу продукта Amazon
   page.goto(
       "https://www.amazon.com/A315-24P-R7VH-Display-Quad-Core-Processor-Graphics/dp/B0BS4BP8FB/",
       timeout=10000,
   )

   # Ожидание полной загрузки страницы
   page.wait_for_load_state("load")

   # Выбор определенного стиля товара из выпадающего меню
   page.locator("#dropdown_selected_style_name").click()

   # Выбор определенной характеристики товара
   page.click('//*[@id="native_dropdown_selected_style_name_1"]')
   page.wait_for_load_state("load")

   # Получение HTML-содержимого загруженной страницы
   html_content = page.content()

   try:
       # Парсинг HTML-содержимого с использованием метода fromstring библиотеки lxml
       parser = fromstring(html_content)

       # Использование XPath для извлечения текстового содержимого названия продукта
       product_title = parser.xpath('//span[@id="productTitle"]/text()')[0].strip()

       # Вывод извлеченного названия продукта
       print({"Product Title": product_title})
   except IndexError:
       # Обработка случая, когда XPath-запрос не возвращает результатов
       print('Product title not found in the specified location.')
   except etree.XMLSyntaxError as parse_err:
       # Обработка синтаксических ошибок XML во время парсинга
       print(f'Error while parsing HTML: {parse_err}')
   except Exception as e:
       # Обработка любых других исключений
       print(f'An unexpected error occurred: {e}')

   # Закрытие браузера и его контекста
   context.close()
   browser.close()


# Использование sync_playwright для запуска сессии Playwright и выполнения скрипта
with sync_playwright() as playwright:
   run(playwright)

Веб-скрапинг с использованием Python является эффективным способом для сбора данных с веб-сайтов. Описанные инструменты позволяют извлекать, обрабатывать и сохранять веб-данные для любых задач. В этом процессе прокси-серверы для смены IP-адресов и задержки между запросами играют ключевую роль, позволяя избегать блокировок. Beautiful Soup представляет собой простой в использовании инструмент для новичков, в то время как для обработки больших объемов данных рекомендуется использовать lxml из-за его производительности. Playwright отлично подходит для продвинутых задач скрапинга благодаря его возможности эффективно взаимодействовать с динамически загружаемыми веб-сайтами на JavaScript.

Комментарии:

0 комментариев