Скрапинг динамических веб-сайтов с помощью Python

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

Веб-скрапинг является ценным инструментом для сбора данных с веб-страниц, особенно когда контент загружается динамически, как на таких сайтах как Pinterest и Instagram. Стандартные методы скрапинга часто оказываются неэффективными для сайтов, где контент генерируется через JavaScript. В данном руководстве мы рассмотрим использование Playwright для автоматизации браузера и lxml для парсинга динамически загружаемых данных.

Будут использоваться следующие инструменты:

  • Playwright для автоматизации браузера;
  • lxml для извлечения данных с помощью XPath;
  • Python в качестве основного языка программирования.

Пошаговое руководство по скрапингу постов Instagram

Мы проиллюстрируем процесс на примере скрапинга профиля в Instagram для извлечения URL-адресов постов, имитируя пользовательские действия, такие как прокрутка страницы и ожидание загрузки новых данных. Динамические сайты асинхронно загружают свой контент через AJAX-запросы, что делает доступным не весь материал страницы сразу.

Шаг 1. Установка необходимых библиотек

Для начала установите следующие пакеты, которые понадобятся для работы:


pip install playwright
pip install lxml

После установки библиотек необходимо установить поддерживаемые Playwright браузеры:


playwright install

Шаг 2. Настройка Playwright для скрапинга динамических сайтов

Для автоматизации браузера и загрузки динамического контента Instagram мы будем использовать Playwright. Ниже приведен базовый скрипт автоматизации для работы в фоновом режиме (headless browser):


import asyncio
from playwright.async_api import async_playwright

async def scrape_instagram():
    async with async_playwright() as p:
        browser = await p.chromium.launch(headless=True)  # Запуск браузера в режиме без отрисовки интерфейса
        page = await browser.new_page()
        
        # Переходим на URL профиля
        await page.goto("https://www.instagram.com/имя профиля", wait_until="networkidle")

        # Нажать кнопку для загрузки большего количества постов 
        await page.get_by_role("button", name="Show more posts from").click()
        
        # Прокрутка страницы для загрузки динамического контента
        scroll_count = 5  # Установите нужное количество прокруток
        for _ in range(scroll_count):
            await page.evaluate('window.scrollBy(0, 700);')
            await page.wait_for_timeout(3000)  # Ожидание загрузки постов
            await page.wait_for_load_state("networkidle")
        
        # Получение контента страницы
        content = await page.content()
        await browser.close()
        
        return content

# Запуск асинхронной функции
asyncio.run(scrape_instagram())

Шаг 3. Парсинг страницы с помощью lxml и XPath

После загрузки содержимого страницы мы можем использовать lxml для парсинга HTML и извлечения данных с помощью XPath. В данном случае мы извлекаем URL-адреса всех постов с профиля.

Код для парсинга содержимого страницы и извлечения URL постов:


from lxml import html
import json

def extract_post_urls(page_content):
    # Парсинг HTML-содержимого с помощью lxml
    tree = html.fromstring(page_content)
    
    # XPath для извлечения URL постов
    post_urls_xpath = '//a[contains(@href, "/p/")]/@href'
    
    # Извлечение URL-адресов
    post_urls = tree.xpath(post_urls_xpath)
    
    # Преобразование относительных URL в абсолютные
    base_url = "https://www.instagram.com"
    post_urls = [f"{base_url}{url}" for url in post_urls]
    
    return post_urls

Функция для сохранения извлеченных данных в формате JSON:


def save_data(profile_url, post_urls):
    data = {profile_url: post_urls}
    with open('instagram_posts.json', 'w') as json_file:
        json.dump(data, json_file, indent=4)

# Запуск скрипта для скрапинга и извлечения URL
page_content = asyncio.run(scrape_instagram())
post_urls = extract_post_urls(page_content)

# Сохранение извлеченных URL в JSON файл
save_data("https://www.instagram.com/имя профиля/", post_urls)

Шаг 4. Управление динамическими страницами с помощью Playwright

Для успешного парсинга динамических сайтов часто требуется имитация бесконечной прокрутки. В нашем скрипте мы используем JavaScript для прокрутки страницы (window.scrollBy(0, 700)) и ожидаем загрузки нового контента с помощью метода wait_for_load_state("networkidle").

Шаг 5. Использование прокси вместе с Playwright

В связи с тем, что Instagram активно борется с автоматическими запросами, важно использовать прокси для обеспечения анонимности и избежания блокировок. Playwright облегчает интеграцию прокси, позволяя ротировать IP-адреса и распределять нагрузку, что снижает вероятность обнаружения скриптов автоматизации.

Пример интеграции прокси в сессию Playwright:


async def scrape_with_proxy():
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=False, 
            proxy={"server": "http://your-proxy-server:port"}
        )
        page = await browser.new_page()
        await page.goto("https://www.instagram.com/имя профиля/", wait_until="networkidle")
        # Продолжайте скрапинг как обычно...

Если требуется авторизация на прокси-сервере, параметры можно дополнить логином и паролем:


async def scrape_with_proxy():
    async with async_playwright() as p:
        browser = await p.chromium.launch(
            headless=False, 
            proxy={"server": "http://your-proxy-server:port", "username": "логин", "password": "пароль"}
        )
        page = await browser.new_page()
        await page.goto("https://www.instagram.com/имя профиля/", wait_until="networkidle")
        # Продолжайте скрапинг как обычно...

Использование прокси не только помогает избегать блокировок по IP и CAPTCHA, но и обеспечивает бесперебойный процесс сбора данных на сайтах с ограничениями доступа, таких как Instagram.

Финальный код


import asyncio
from playwright.async_api import async_playwright
from lxml import html
import json

# Функция для автоматизации браузера и скрапинга динамичного контента с прокси
async def scrape_instagram(profile_url, proxy=None):
    async with async_playwright() as p:
        # Настройка браузера с прокси
        browser_options = {
            'headless': True,  # Используйте браузер с интерфейсом, чтобы видеть действия (можно установить в True для режима без интерфейса)
        }
        if proxy:
            browser_options['proxy'] = proxy

        # Запуск браузера
        browser = await p.chromium.launch(**browser_options)
        page = await browser.new_page()

        # Переход на страницу профиля Instagram
        await page.goto(profile_url, wait_until="networkidle")
        
        # Попытка нажать кнопку “Показать больше постов” (опционально, может не сработать, если кнопка не найдена)
        try:
           await page.click('button:has-text("Show more posts from")')
        except Exception as e:
           print(f"No 'Show more posts' button found: {e}")


        # Прокрутка страницы для загрузки большего количества постов
        scroll_count = 5  # Количество прокруток для загрузки постов
        for _ in range(scroll_count):
            await page.evaluate('window.scrollBy(0, 500);')
            await page.wait_for_timeout(3000)  # Ожидание загрузки новых постов
            await page.wait_for_load_state("networkidle")

        # Получение полного содержимого страницы после прокрутки
        content = await page.content()
        await browser.close()  # Закрытие браузера после завершения
        
        return content

# Функция для парсинга содержимого страницы и извлечения URL постов
def extract_post_urls(page_content):
    # Парсинг HTML-содержимого с помощью lxml
    tree = html.fromstring(page_content)
    
    # XPath для извлечения URL постов
    post_urls_xpath = '//a[contains(@href, "/p/")]/@href'
    
    # Извлечение URL постов с использованием XPath
    post_urls = tree.xpath(post_urls_xpath)
    
    # Преобразование относительных URL в абсолютные
    base_url = "https://www.instagram.com"
    post_urls = [f"{base_url}{url}" for url in post_urls]
    
    return post_urls

# Функция для сохранения извлеченных URL постов в файл JSON
def save_data(profile_url, post_urls):
    # Структурирование данных в формате JSON
    data = {profile_url: post_urls}
    
    # Сохранение данных в файл
    with open('instagram_posts.json', 'w') as json_file:
        json.dump(data, json_file, indent=4)
    print(f"Data saved to instagram_posts.json")

# Основная функция для запуска скрапера и сохранения данных
async def main():
    # Определение URL профиля Instagram
    profile_url = "https://www.instagram.com/имя профиля/"
    
    # При необходимости настройте прокси
    proxy = {"server": "server", "username": "username", "password": "password"}  # Use None if no proxy is required
    
    # Скрапинг страницы Instagram с прокси
    page_content = await scrape_instagram(profile_url, proxy=proxy)
    
    # Извлечение URL постов из содержимого страницы
    post_urls = extract_post_urls(page_content)
    
    # Сохранение извлеченных URL постов в файл JSON
    save_data(profile_url, post_urls)

if __name__ == '__main__':
   asyncio.run(main())

Альтернативные инструменты автоматизации для веб-скрапинга

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

  1. Selenium: этот фреймворк является одним из наиболее устоявшихся инструментов для автоматизации веб-браузеров. Selenium поддерживает широкий спектр браузеров и языков программирования, обеспечивая высокую универсальность, хотя он может уступать в некоторых аспектах современности по сравнению с Playwright, например, в управлении сессиями браузеров через единый API.
  2. Puppeteer: разработанный Google, этот инструмент оптимизирован для работы с Chromium и предоставляет мощные возможности для скрапинга сайтов, активно использующих JavaScript. Puppeteer идеально подходит для работы в режиме без отрисовки интерфейса, позволяя легко взаимодействовать с динамическими элементами веб-страниц.
  3. Requests и BeautifulSoup: эта комбинация библиотек хорошо подходит для скрапинга статичных веб-страниц, где JavaScript не играет ключевой роли в отображении контента. Хотя это решение не подходит для работы с динамическими сайтами, его простота и легкость в использовании делают его идеальным для начинающих и проектов, не требующих сложной обработки веб-страниц.

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

Для успешного скрапинга динамических веб-сайтов, активно использующих JavaScript и AJAX-запросы, необходимы мощные инструменты, способные эффективно обрабатывать бесконечную прокрутку и сложные интерактивные элементы. Одним из таких решений является Playwright — инструмент от Microsoft, обеспечивающий полную автоматизацию браузера, что делает его идеальным выбором для работы с платформами, такими как Instagram. В сочетании с библиотекой lxml для анализа HTML, Playwright значительно упрощает извлечение данных, позволяя автоматизировать взаимодействие с элементами страницы и процесс парсинга без ручного вмешательства. Кроме того, использование прокси-серверов помогает обходить антибот-защиту и предотвращает блокировку по IP, обеспечивая стабильную и бесперебойную работу скрапинга.

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

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