Посібник зі скрапінгу 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. Варто зазначити, що проксі з ротацією дадуть змогу уникнути виявлення скрапера з боку Reddit. До них відносяться мобільні та резидентські динамічні проксі, що володіють найвищим траст-фактором у мережі та дають змогу збирати дані без виникнення капчі та блокувань.

Коментарії:

0 Коментаріїв