如何使用Python刮擦Reddit

评论: 0

Reddit刮擦提供了有关趋势主题,社区参与和流行帖子的大量信息。尽管Reddit的官方API是访问此类内容的常见工具,但它的局限性可以通过提供更大的数据选择灵活性来克服刮擦。本教程将指导您使用异步的剧作家库来管理动态内容和LXML库来提取数据,从而允许全面刮擦Reddit的方法。

步骤1:设置环境

启动之前,请确保您已安装Python和所需的库:

pip install playwright
pip install  lxml

安装必要的库后,您需要安装剧作家浏览器二进制文件:

playwright install

要安装铬浏览器,请使用以下命令:

Playwright install chromium

这些工具将帮助我们与Reddit的动态内容进行互动,解析HTML并提取所需的数据。

步骤2:使用剧作家获取页面内容

剧作家是一种强大的工具,可让我们像人类用户一样控制浏览器并与网页进行交互。我们将使用它加载Reddit页面并获取HTML内容。

这是加载reddit页面的剧作作者async代码:

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地址和自定义标头旋转以模仿真实的用户行为。

使用代理

刮擦时,您可能会遇到诸如限制速率或IP阻塞之类的问题。为了减轻这些方法,您可以使用代理将IP地址和自定义标头旋转以模仿真实的用户行为。代理可用于旋转IP地址并避免检测。这可以由您的服务提供商来处理,以确保他们管理IPS池并根据需要旋转它们。

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://www.reddit.com/r/technology/top/?t=week", wait_until='networkidle')
        page_content = await page.content()
        await browser.close()
        return page_content

步骤3:用LXML解析HTML内容

一旦拥有HTML内容,下一步就是对其进行解析并使用LXML提取相关数据。

from lxml import html

# 解析HTML内容
parser = html.fromstring(page_content)

识别要刮擦的元素

关于Reddit的R/Technology SubReddit的顶级帖子包含在文章元素中。这些元素可以使用以下XPath来定位:

# 提取个人帖子元素
elements = parser.xpath('//article[@class="w-full m-0"]')

使用XPath进行数据提取

XPath是从HTML文档导航和选择节点的强大工具。我们将使用它从每个帖子中提取标题,链接和标签。

这是每个数据点的特定XPATH:

Title: @aria-label
Link: .//div[@class="relative truncate text-12 xs:text-14 font-semibold mb-xs "]/a/@href
Tag: .//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")

完成代码

这是刮擦R/技术中Reddit的顶级帖子的完整代码,并将数据保存为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://www.reddit.com/r/technology/top/?t=week", wait_until='networkidle')
        page_content = await page.content()
        await browser.close()
        return page_content

# 获取页面内容
page_content = asyncio.run(fetch_page_content())

# 使用LXML解析HTML含量
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 评论