You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用RStudio调用Reddit API爬取r/coding帖子遇问题求助

问题解决:Reddit API爬取限制与时间范围无结果问题

问题原因分析

  1. 未使用认证令牌:代码中获取了access_token,但后续GET请求未携带Authorization头,导致以匿名身份访问API,这类访问有严格的条数和请求次数限制。
  2. 数据绑定逻辑错误:直接用rbind处理列表格式的posts会导致数据结构混乱,字段丢失或类型错误,影响后续时间过滤。
  3. 时间判断逻辑缺陷:循环终止条件中any(last_post_time < start_time)会在单条帖子时间早于开始时间时直接终止,可能遗漏前面符合时间范围的帖子。
  4. 时间字段混淆:最后打印用了created(本地时间),但处理时用的是created_utc(UTC时间),时间基准不一致导致过滤失效。

修正后的代码

# 安装所需包
install.packages("jsonlite")
install.packages("tidyverse")
install.packages("httr")

# 加载所需库
library(jsonlite)
library(tidyverse)
library(httr)

# 设置Reddit应用凭证
client_id <- ""
client_secret <- ""
username <- ""
password <- ""
user_agent <- "你的应用名称/版本 (联系邮箱)"  # 必须填写规范的User-Agent

# 认证并获取访问令牌
token_url <- "https://www.reddit.com/api/v1/access_token"
response <- POST(token_url,
                 body = list(
                   grant_type = "password",
                   username = username,
                   password = password
                 ),
                 add_headers("User-Agent" = user_agent),
                 authenticate(client_id, client_secret),
                 encode = "form"
)

# 检查认证是否成功
if (http_status(response)$category != "Success") {
  stop("认证失败:", content(response)$error_description)
}
access_token <- content(response)$access_token

# 定义时间范围(统一使用UTC时间)
start_time <- as.POSIXct("2022-11-01", tz = "UTC")
end_time <- Sys.time()

# 初始化数据存储
all_posts <- tibble()
after <- ""

repeat {
  # 发送带认证的API请求,指定每页最多获取100条(Reddit API允许的最大值)
  response <- GET(
    "https://oauth.reddit.com/r/coding/new/.json",  # 使用OAuth专属端点
    query = list(after = after, limit = 100),
    add_headers(
      "User-Agent" = user_agent,
      "Authorization" = paste("Bearer", access_token)  # 携带认证令牌
    )
  )
  
  # 检查响应状态
  if (http_status(response)$category != "Success") {
    warning("请求失败:", http_status(response)$reason)
    break
  }
  if (http_type(response) != "application/json") {
    stop("错误:未获取到JSON格式数据")
  }
  
  data <- content(response)$data
  posts <- data$children$data
  
  if (length(posts) == 0) {
    break
  }
  
  # 将当前页帖子转为数据框并合并到总数据
  current_posts <- bind_rows(posts)
  all_posts <- bind_rows(all_posts, current_posts)
  
  # 转换当前页帖子的UTC时间
  current_posts$timestamp <- as.POSIXct(current_posts$created_utc, origin = "1970-01-01", tz = "UTC")
  
  # 检查当前页是否存在早于开始时间的帖子,若有则过滤后终止循环
  if (any(current_posts$timestamp < start_time)) {
    current_posts_filtered <- current_posts[current_posts$timestamp >= start_time, ]
    all_posts <- bind_rows(all_posts %>% filter(timestamp >= start_time), current_posts_filtered)
    break
  }
  
  # 更新分页标记,无更多分页则终止
  after <- data$after
  if (is.null(after)) {
    break
  }
  
  Sys.sleep(2)  # 遵守API速率限制
}

# 最终过滤时间范围并选择字段
filtered_posts <- all_posts %>%
  filter(timestamp >= start_time & timestamp <= end_time) %>%
  select(ups, title, subreddit, url, selftext, timestamp)

# 展示结果
print(filtered_posts)

关键修正点说明

  • 使用OAuth端点:请求地址改为https://oauth.reddit.com,是认证后请求的标准端点。
  • 携带认证令牌:添加Authorization头提升访问权限,解除匿名访问的条数限制。
  • 设置最大分页条数:通过limit=100让每页返回最多100条数据,减少请求次数。
  • 正确数据绑定:用bind_rows处理列表格式帖子,避免rbind导致的结构错误。
  • 优化时间终止逻辑:检查当前页所有帖子时间,仅当存在早于开始时间的帖子时,过滤后再终止,确保获取全部符合条件的内容。
  • 统一时间字段:全程使用created_utc转换的UTC时间戳,避免时间基准不一致的问题。

内容的提问来源于stack exchange,提问作者Ejudah

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 04:08:11