Скрапінг динамічних веб-сайтів за допомогою 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"}  # Використовуйте None, якщо проксі не потрібен
    
    # Скрапінг сторінки 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 Коментаріїв