2024 年使用 Python 抓取 Reddit 的终极指南
对于希望收集见解和训练人工智能模型的企业、研究人员和开发人员来说,Reddit 是一个宝贵数据的金矿。但到了 2023 年,Reddit 对 API 访问收取了巨额费用,打乱了许多人的计划。幸运的是,网页抓取提供了一种更有效、更经济、更灵活的替代方案。在本深入指南中,我们将引导您准确了解如何使用 Python 和 Selenium 从 Reddit 中抓取数据。
2023 年 4 月,Reddit 宣布他们将开始对 API 访问收取高额费用——每 1000 次调用 0.24 美元。对于大多数用例来说,这一更改立即导致 API 成本过高。许多像 Apollo 这样依赖 API 的应用程序被迫关闭。
但 Reddit 上的大量有用数据并没有突然消失或失去价值。人们仍然需要访问它来进行商业智能、科学研究、训练大型语言模型等。网络抓取现在是大规模获取这些数据的最可行和最具吸引力的方法。
与使用官方 API 相比,以下是抓取 Reddit 的一些主要优势:
-
节省成本——通过抓取,您可以收集 Reddit 数据,而无需支付高昂的 API 费用。唯一的成本是您自己的计算资源。
-
提高灵活性 – 通过抓取,您可以精确定位所需的确切数据,而不受 API 约束的限制。自定义您的抓取工具以提取您想要的字段。
-
访问更多数据 – API 通常会限制可用数据的范围。抓取时,您可以访问网站上的任何公共数据,包括未通过官方渠道提供的信息。
因此,在 2024 年的后 API 世界中,网络抓取是从 Reddit 收集数据的明智选择。让我们深入了解如何使用 Python 实现这一点的技术细节!
抓取 Reddit 所需的工具
要学习本教程,请确保您具备以下条件:
- 已安装 Python 3.7+
- Python IDE(PyCharm、VS Code 等)
- Chrome 网络浏览器
- 用于 Selenium 的 ChromeDriver
我们将使用 Python Selenium 库来自动化 Chrome 浏览器并从 Reddit 抓取数据。 Selenium 是理想的选择,因为它可以呈现 Reddit 页面上常见的动态 JavaScript 内容。
您还需要设置一个虚拟环境来管理 Reddit 抓取项目的依赖项。通过运行以下命令来执行此操作:
python -m venv env
source env/bin/activate
然后安装必要的Python包:
pip install selenium webdriver-manager
太棒了,你已经准备好了!让我们开始构建 Reddit 抓取工具。
Reddit 抓取分步教程
我们将从 r/technology subreddit 中抓取数据作为示例。但您可以轻松地调整此代码以从任何公共 subreddit 中提取帖子和信息。
第 1 步 – 设置 Selenium
首先,导入所需的 Selenium 模块并将 Chrome 配置为以无头模式运行。这会隐藏浏览器 UI,从而节省资源。
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
options = Options()
options.headless = True
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()),
options=options)
指定您要抓取的 Reddit 子版块的 URL。在本例中,我们将获取过去一周有关 r/technology 的热门帖子。
url = "https://www.reddit.com/r/technology/top/?t=week"
driver.get(url)
第 3 步 – 抓取 Subreddit 元数据
Reddit 子页面的顶部包含有用的元数据。让我们抓取名称、描述、创建日期和成员数量。
subreddit = {}
subreddit[‘name‘] = driver.find_element(By.TAG_NAME, ‘h1‘).text
subreddit[‘description‘] = driver.find_element(By.XPATH,
"//div[@data-testid=‘DescriptionComment‘]").text
subreddit[‘created‘] = driver.find_element(By.XPATH,
"//span[contains(text(), ‘Created‘)]/following-sibling::span").text
subreddit[‘members‘] = driver.find_element(By.XPATH,
"//div[@id=‘MembershipButton‘]//span[@class=‘_vaFo96phV6L5Hltvwcox‘]").text
第 4 步 – 抓取帖子数据
接下来,让我们收集 Reddit 子版块中每个帖子的数据。我们将获取热门帖子的标题、作者、点赞数、评论数和目标 URL。
检查 HTML 以查找包含此数据的元素。 Reddit 通过使用随机生成的 CSS 类使其变得棘手。但是我们可以使用语义属性可靠地选择元素,例如data-testid。
posts = []
post_elems = driver.find_elements(By.CSS_SELECTOR,
‘[data-testid="post-container"]‘)
for post in post_elems:
post_data = {}
post_data[‘title‘] = post.find_element(By.TAG_NAME, ‘h3‘).text
post_data[‘author‘] = post.find_element(By.CSS_SELECTOR,
‘[data-testid="post_author_link"]‘).text
post_data[‘upvotes‘] = post.find_element(By.XPATH,
"//div[@data-click-id=‘upvote‘]/following-sibling::div").text
post_data[‘comments‘] = post.find_element(By.XPATH,
"//a[@data-click-id=‘comments‘]/span").text
post_data[‘url‘] = post.find_element(By.CSS_SELECTOR,
‘[data-testid="outbound-link"]‘).get_attribute(‘href‘)
posts.append(post_data)
将此帖子数据添加到 subreddit 字典中:
subreddit[‘posts‘] = posts
步骤 5 – 输出抓取的数据
最后,将抓取的 subreddit 数据保存到 JSON 文件中,以便于在其他应用程序中使用。漂亮地打印 JSON 以使其更易于阅读。
import json
with open(‘subreddit_data.json‘, ‘w‘) as f:
json.dump(subreddit, f, indent=4)
把它们放在一起
下面是从 Reddit subreddit 中抓取数据的完整 Python 脚本:
from selenium import webdriver
from selenium.webdriver.chrome.service import Service as ChromeService
from webdriver_manager.chrome import ChromeDriverManager
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import json
options = Options()
options.headless = True
driver = webdriver.Chrome(service=ChromeService(ChromeDriverManager().install()),
options=options)
url = "https://www.reddit.com/r/technology/top/?t=week"
driver.get(url)
subreddit = {}
subreddit[‘name‘] = driver.find_element(By.TAG_NAME, ‘h1‘).text
subreddit[‘description‘] = driver.find_element(By.XPATH, "//div[@data-testid=‘DescriptionComment‘]").text
subreddit[‘created‘] = driver.find_element(By.XPATH, "//span[contains(text(), ‘Created‘)]/following-sibling::span").text
subreddit[‘members‘] = driver.find_element(By.XPATH, "//div[@id=‘MembershipButton‘]//span[@class=‘_vaFo96phV6L5Hltvwcox‘]").text
posts = []
post_elems = driver.find_elements(By.CSS_SELECTOR, ‘[data-testid="post-container"]‘)
for post in post_elems:
post_data = {}
post_data[‘title‘] = post.find_element(By.TAG_NAME, ‘h3‘).text
post_data[‘author‘] = post.find_element(By.CSS_SELECTOR, ‘[data-testid="post_author_link"]‘).text
post_data[‘upvotes‘] = post.find_element(By.XPATH, "//div[@data-click-id=‘upvote‘]/following-sibling::div").text
post_data[‘comments‘] = post.find_element(By.XPATH, "//a[@data-click-id=‘comments‘]/span").text
post_data[‘url‘] = post.find_element(By.CSS_SELECTOR, ‘[data-testid="outbound-link"]‘).get_attribute(‘href‘)
posts.append(post_data)
subreddit[‘posts‘] = posts
with open(‘subreddit_data.json‘, ‘w‘) as f:
json.dump(subreddit, f, indent=4)
driver.quit()
运行这个脚本,你会得到一个格式良好的subreddit_data.json包含所有抓取的 Reddit 数据的文件。您现在已经准备好按照您的意愿分析数据了!
大规模抓取 Reddit 的先进技术
上面的基本脚本非常适合抓取单个 Reddit 子版块。但如果你需要收集更大规模的 Reddit 数据,你可能会遇到一些挑战:
-
速率限制和 IP 禁令 – 如果您过快地发出过多请求,Reddit 将限制或阻止您的 IP。这可能会让你的刮擦完全停止。
-
验证码和其他反机器人措施 – Reddit 采用各种防御措施来阻止机器人和抓取工具。您可能会收到验证码,以防止进一步抓取。
-
抓取速度慢——Selenium 可靠,但与其他抓取方法相比相对较慢。抓取大型子版块可能非常耗时。
要大规模抓取 Reddit 数据,您需要解决这些问题。以下是一些提示:
- 使用轮换代理来避免速率限制和禁令。代理允许您从许多不同的 IP 地址发出请求。自动代理轮换让您可以继续抓取而不会遇到障碍。
寻找来自信誉良好的提供商的快速、安全、符合道德的代理。根据我所做的评论和基准测试,以下是一些值得考虑的顶级代理服务:
- 明亮的数据
- 皇家IP
- 代理卖家
- SOAX
- 智能代理
- 廉价代理
- 水代理
-
使用 2Captcha 或 Anticaptcha 等服务自动处理 CAPTCHA。这些廉价的服务通过 API 为您解决验证码,以便您可以继续进行抓取。
-
通过并行运行多个抓取器来优化抓取速度和效率。您可以将 Reddit 抓取工具部署在 Docker Swarm 或 Kubernetes 等平台上,以同时运行多个实例并更快地收集数据。
-
或者,使用专门构建的抓取工具,例如 Bright Data 的抓取浏览器。它会自动为您处理验证码和反抓取措施,同时让您的抓取速度比 Selenium 更快。
总结
由于 API 成本过高,网络抓取现在已成为收集 Reddit 数据的首选方法。借助本指南中介绍的 Python 脚本和技术,您已经做好了充分准备,可以可靠、高效地从 Reddit 中获取大量有价值的数据。
请记住,在抓取数据时始终保持尊重,并避免同时因太多请求而导致 Reddit 服务器超载。使用代理并调整您的抓取率,成为一个好公民。
如果您想跳过自己抓取 Reddit 的棘手过程,您还可以从各种在线来源购买现成的 Reddit 数据集。但是构建自己的抓取工具可以为您提供最大的灵活性和最新的数据。
现在,您拥有了利用 Reddit 上丰富的数据进行业务、研究或编码项目所需的一切。那你还等什么?立即开始使用 Python 抓取 Reddit!
