【问题标题】:RedditExtractoR: reddit_urls() does not return all resultsRedditExtractoR:reddit_urls() 不返回所有结果
【发布时间】:2021-01-02 02:50:51
【问题描述】:

我正在尝试使用 R 包 RedditExtractoR 从 Reddit 进行网络抓取。具体来说,我使用 reddit_urls() 从 Reddit 中返回搜索词“总统”的结果。

我首先创建了一个对象links499,它(应该)包含 499 页包含“总统”一词的 URL。我是按 cmets 排序的。

links499 <- reddit_urls(search_terms = "president",
  cn_threshold = 0,
  page_threshold = 499,
  sort_by = "comments",
  wait_time = 2)

links499Com <- get_reddit(search_terms = "president", 
  cn_threshold = 0,
  page_threshold = 499,
  sort_by = "comments",
  wait_time =2)

这些对象中的每一个都具有相同数量的唯一 URL 标题 (n=239),并且都只返回了具有非常多 cmets 的 URL(其中最低的是 12,378)。这是有道理的,因为我是按照 cmets 数量递减的顺序从 Reddit 中提取 URL。

# Have the same number of unique titles
unique(links499$title)
unique(links499Com$title)

# Both have minimum of 12378
min(links499$num_comments)
min(links499Com$num_comments)

接下来,我想为 Reddit 中的搜索词“president”返回更多匹配的 URL。我认为这可以通过简单地增加page_threshold 参数来实现。但是,我(未成功)尝试了相同的代码,现在只搜索了 1000 个页面的 URL。

links1000 <- reddit_urls(search_terms = "president",
  cn_threshold = 0,
  page_threshold = 1000,
  sort_by = "comments",
  wait_time = 2)

links1000Com <- get_reddit(search_terms = "president", 
  cn_threshold = 0,
  page_threshold = 1000,
  sort_by = "comments",
  wait_time =2)

我认为links1000 将包含来自 1000 个 cmet 数量最多的页面中搜索词为“president”的 URL(而links499 将包含来自 499 个页面中搜索词为“president”的 URL厘米)。但是,links1000links499 是相同的。

另外,links1000Com 无法创建并抛出错误:URL 'https://www.reddit.com/r/politics/comments/dzd8lu/discussion_thread_fifth_democratic_presidential/.json?limit=500': status was 'Failure when receiving data from the peer'

似乎有 500 页的限制。

我的问题是:接下来我将如何获取所有 URL(及其相关的 cmets)?不仅是前 499 个页面或前 1000 个页面,而是要继续直到在 Reddit 中搜索词为“总统”的所有个 URL 都被返回?

感谢您分享任何建议。

*** 编辑 ***

按照建议,我在下面添加了可重现的代码。再次感谢!

library(tidyverse)
library(RedditExtractoR)

links499 <- reddit_urls(search_terms = "president",
                        cn_threshold = 0, # minimum number of comments
                        page_threshold = 499,
                        sort_by = "comments",
                        wait_time = 2)

links499Com <- get_reddit(search_terms = "president", 
                          cn_threshold = 0,
                          page_threshold = 499,
                          sort_by = "comments",
                          wait_time =2)

# Have the same number of unique titles (n=239)
length(unique(links499$title))
length(unique(links499Com$title))

# Both have minimum of 12378
min(links499Com$num_comments)
min(links499$num_comments)

links1000 <- reddit_urls(
    search_terms = "president",
    cn_threshold = 0, # minimum number of comments
    page_threshold = 1000, # can probably get as many URLs as you want but you can only extract a certain amount of data at one time
    sort_by = "comments",
    wait_time = 2
)

links1000Com <- get_reddit(search_terms = "president", 
                          cn_threshold = 0,
                          page_threshold = 1000,
                          sort_by = "comments",
                          wait_time =2 )

# Have the same number of unique titles (n=241)
length(unique(links1000$title))
length(unique(links1000Com$title))

# Both have minimum of 12378
min(links1000Com$num_comments)
min(links1000$num_comments)

【问题讨论】:

  • 当前代码为 sn-p 格式,缺少所需的库调用。一条建议。您可以在 Q 中的某个地方发布您尝试过的完整代码。这样其他人就可以重现问题而不重复代码。我建议在 Q 的末尾添加它。

标签: r web-scraping reddit


【解决方案1】:

因此,查看get_redditreddit_urls 的代码,您会发现get_redditreddit_urls 的包装,并且这两个函数的默认值完全不同。 get_reddit, reddit_urls.

但是,您的问题的答案是:You can't get more than 1000 results to a search query.

限制和注意事项

  • 搜索词可能会被阻止。搜索“dogs”可能会返回包含“dog”一词的结果。
  • 搜索结果限制为 1000 个结果。

您的错误消息中的limit=500 参数指的是要返回的所需帖子数,而不是所需的页数。 reddit 进行分页的方式与您预期的不同。基本上他们会跟踪帖子的顺序,然后为了获得下一组帖子(新页面),您将最后一个帖子的 ID 传递给您的呼叫。我认为 reddit 会跟踪呼叫的发起者(您的计算机)并限制其返回的金额。

This decribes reddit's API (in particular before and after)

Here is a resource in Python which describes limitations on reddit's API.


编辑:

我也不清楚为什么我们没有得到我们要求的结果数量。我注意到的一件事是,Reddit 似乎在浏览了一定数量的页面后停止提供进一步结果的键。目前尚不清楚这是基于什么。我写了一些代码来检查一下,看看我是否可以自己拉出结果:

search_query = "president"
number_of_pages = 10

results_holder <- data_frame(page = 1:number_of_pages, search = character(length = number_of_pages), titles = as.list(rep(1, number_of_pages)), url = as.list(rep(1, number_of_pages)))

first_search <- paste0("https://www.reddit.com/search/.json?q=",search_query,"&limit=1000&sort=comment")

tmp <- read_lines(first_search)
tmp2 <- jsonlite::fromJSON(tmp)
results_holder$search[1] <- first_search
results_holder$titles[[1]] <- tmp2$data$children$data$title
results_holder$url[[1]] <- tmp2$data$children$data$permalink
last_name <- tmp2$data$after

for(i in 2:number_of_pages){
  new_search = paste0("https://www.reddit.com/search/.json?q=",search_query,"&limit=1000&sort=comment&after=",last_name)
  tmp_loop <- read_lines(new_search)
  tmp2_loop <- jsonlite::fromJSON(tmp_loop)
  results_holder$search[i] <- new_search
  results_holder$titles[[i]] <- tmp2_loop$data$children$data$title
  results_holder$url[[i]] <- tmp2_loop$data$children$data$permalink
  last_name <- tmp2_loop$data$after
  Sys.sleep(5)
}

从中您可以检查对象results_holder$search 并看到最终我们在分页中重新开始。

我看到发生的事情(并且可以通过在浏览器中执行相同的操作来验证)是 reddit 停止在 json 文件中为 after 提供值。这是我们构建新搜索字符串并获取下一页所需的值。 有时我可以让它在它开始给出"after": null之前返回3页/~250个结果@

【讨论】:

  • 感谢@BrianLang。我以前没见过这个。但是,即使有了这些信息,我仍然不确定为什么 links1000links499 在我上面的代码中是相同的。如果限制是 1000,links1000 不应该是 links499 的两倍吗?我还想知道是否有一种方法可以运行具有 1000 个结果(前 1000 个、下一个 1000、下一个 1000 等)的顺序抓取?我原以为等待wait_time 参数用于(在必要的等待期后运行下一个n 搜索结果,因为在给定时间只能执行n=1000)。
  • 是的,这很奇怪。在查看了包的代码之后,他们基本上向 R 发送了页面请求,中间有一段时间 wait_time。这些请求是顺序的,并且依赖于返回的 json 文件 after 中的变量来引导到下一页。问题似乎是 reddit 只愿意在 after 返回为 null 之前提供一定数量的页面。这似乎坚定地站在了 reddit 的一边。
猜你喜欢
  • 2021-06-21
  • 2015-10-23
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-15
  • 1970-01-01
相关资源
最近更新 更多