Руководство по скрапингу Reddit с использованием Python

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

Скрапинг Reddit может предоставить ценные сведения о трендовых темах, активности сообществ и популярных постах. Хотя для доступа к контенту часто используется официальный API, он накладывает определённые ограничения, в то время как скрапинг предоставляет больше возможностей для выбора данных для извлечения. В этом руководстве мы покажем, как осуществлять скрапинг Reddit с помощью асинхронной библиотеки Playwright для обработки динамического содержимого и lxml для извлечения данных.

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

Перед началом убедитесь, что у вас установлен Python и необходимые библиотеки:


pip install playwright
pip install  lxml

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

playwright install

Для установки только браузера Chromium используйте следующую команду:

Playwright install chromium

Эти инструменты помогут вам взаимодействовать с динамическим содержимым Reddit, парсить HTML и извлекать необходимые данные.

Шаг 2: Получение содержимого страницы с помощью Playwright

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

Ниже представлен код, который использует асинхронный подход Playwright для загрузки страницы Reddit:

import asyncio
from playwright.async_api import async_playwright

async def fetch_page_content():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch(headless=False)
        context = await browser.new_context()
        page = await context.new_page()
        await page.goto("https://www.reddit.com/r/technology/top/?t=week")
        page_content = await page.content()
        await browser.close()
        return page_content

# Получение содержимого страницы
page_content = asyncio.run(fetch_page_content())

Использование прокси

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

async def fetch_page_content_with_proxy():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch(headless=True, proxy={
            "server": "http://proxy-server:port",
            "username": "your-username",
            "password": "your-password"
        })
        context = await browser.new_context()
        page = await context.new_page()
        await page.goto("ссылка HTTPS", wait_until='networkidle')
        page_content = await page.content()
        await browser.close()
        return page_content

Шаг 3: Парсинг HTML-контента с помощью lxml

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

from lxml import html

# Парсинг HTML-контента
parser = html.fromstring(page_content)

Идентификация элементов для скрапинга

Топовые посты на сабреддите r/technology Reddit содержатся в элементах article. Эти элементы можно извлечь с помощью следующего XPath:

# Извлечение элементов отдельного поста
elements = parser.xpath('//article[@class="w-full m-0"]')

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

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

Заголовок: @aria-label
Ссылка: .//div[@class="relative truncate text-12 xs:text-14 font-semibold mb-xs "]/a/@href
Тег: .//span[@class="bg-tone-4 inline-block truncate max-w-full text-12 font-normal align-text-bottom text-secondary box-border px-[6px] rounded-[20px] leading-4 relative top-[-0.25rem] xs:top-[-2px] my-2xs xs:mb-sm py-0 "]/div/text()

Шаг 4: Извлечение данных из каждого поста

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

posts_data = []

# Перебор каждого элемента поста
for element in elements:
    title = element.xpath('@aria-label')[0]
    link = element.xpath('.//div[@class="relative truncate text-12 xs:text-14 font-semibold  mb-xs "]/a/@href')[0]
    tag = element.xpath('.//span[@class="bg-tone-4 inline-block truncate max-w-full text-12 font-normal align-text-bottom text-secondary box-border px-[6px] rounded-[20px] leading-4  relative top-[-0.25rem] xs:top-[-2px] my-2xs xs:mb-sm py-0 "]/div/text()')[0].strip()
    
    post_info = {
        "title": title,
        "link": link,
        "tag": tag
    }
    
    posts_data.append(post_info)

Шаг 5: Сохранение данных в формате JSON

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

import json

# Сохранение данных в файл JSON
with open('reddit_posts.json', 'w') as f:
    json.dump(posts_data, f, indent=4)

print("Data extraction complete. Saved to reddit_posts.json")

Финальная версия кода

Вот полный код для парсинга данных с Reddit из подраздела r/technology и сохранения их в формате JSON:

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

async def fetch_page_content():
    async with async_playwright() as playwright:
        browser = await playwright.chromium.launch(headless=True, proxy={
            "server": "IP:port",
            "username": "your-username",
            "password": "your-password"
        })
        context = await browser.new_context()
        page = await context.new_page()
        await page.goto("Ссылка HTTPS", wait_until='networkidle')
        page_content = await page.content()
        await browser.close()
        return page_content

# Получаем содержимое страницы
page_content = asyncio.run(fetch_page_content())

# Парсим HTML содержимое с помощью lxml
parser = html.fromstring(page_content)

# Извлекаем элементы каждого поста
elements = parser.xpath('//article[@class="w-full m-0"]')

# Инициализируем список для хранения извлеченных данных
posts_data = []

# Перебираем каждый элемент поста
for element in elements:
    title = element.xpath('@aria-label')[0]
    link = element.xpath('.//div[@class="relative truncate text-12 xs:text-14 font-semibold  mb-xs "]/a/@href')[0]
    tag = element.xpath('.//span[@class="bg-tone-4 inline-block truncate max-w-full text-12 font-normal align-text-bottom text-secondary box-border px-[6px] rounded-[20px] leading-4  relative top-[-0.25rem] xs:top-[-2px] my-2xs xs:mb-sm py-0 "]/div/text()')[0].strip()
    
    post_info = {
        "title": title,
        "link": link,
        "tag": tag
    }
    
    posts_data.append(post_info)

# Сохраняем данные в файл JSON
with open('reddit_posts.json', 'w') as f:
    json.dump(posts_data, f, indent=4)

print("Data extraction complete. Saved to reddit_posts.json")

Данный подход позволяет скрапить разнообразные сабреддиты, собирая ценную информацию из обширных обсуждений в сообществах Reddit. Стоит отметить что прокси c ротацией позволят избежать обнаружения скрапера со стороны Reddit. К ним относятся мобильные и резидентские динамические прокси, обладающие наиболее высоким траст-фактором в сети и позволяющие собирать данные без возникновения капчи и блокировок.

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

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