RedditExtractoR: reddit_urls() возвращает не все результаты

#r #web-scraping #reddit

#r #очистка веб-страниц #Reddit

Вопрос:

Я пытаюсь выполнить webscrape из Reddit, используя R-пакет RedditExtractoR. В частности, я использую reddit_urls() для возврата результатов из Reddit с поисковым запросом «президент».

Сначала я создал объект links499 , который (должен) содержать URL-адреса на 499 страниц, содержащие термин «президент». Я отсортировал по комментариям.

 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), и оба возвращали только URL с очень большим количеством комментариев (наименьший из которых был 12 378). Это имеет смысл, потому что я извлекаю URL-адреса из Reddit в порядке уменьшения количества комментариев.

 # 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)
  

Затем я хотел вернуть еще большее количество совпадающих URL-адресов для поискового запроса «президент» из Reddit. Я думал, что этого можно добиться простым увеличением page_threshold параметра. Однако я (безуспешно) попробовал тот же код, только теперь выполнив поиск по URL-адресам на 1000 страниц.

 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 будет содержать URL-адреса с поисковым запросом «президент» с 1000 страниц с наибольшим количеством комментариев (тогда как links499 будет содержать URL-адреса с поисковым запросом «президент» с 499 страниц с наибольшим количеством комментариев). Однако links1000 и links499 были идентичны.

Более того, 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-адреса (и связанные с ними комментарии)? Не только для 499 лучших страниц или 1000 лучших страниц, но продолжать до тех пор, пока не будут возвращены все URL-адреса с поисковым термином «президент» в Reddit?

Спасибо, что поделились любым советом.

*** РЕДАКТИРОВАТЬ ***

Как и было предложено, я добавляю воспроизводимый код ниже. Еще раз спасибо!

 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)
  

Комментарии:

1. Текущий код находится в формате фрагмента и в нем отсутствуют необходимые вызовы библиотеки. Предложение. Где-нибудь в своем Q вы можете опубликовать полный код, который вы пробовали. Чтобы другие могли воспроизвести проблему, а также не повторять код. Я предлагаю добавить его в конце Q.

Ответ №1:

Итак, взглянув на код для get_reddit и reddit_urls , вы увидите, что get_reddit это оболочка для reddit_urls и что значения по умолчанию просто различаются между двумя функциями. get_reddit , reddit_urls .

Однако ответ на ваш вопрос таков: вы не можете получить более 1000 результатов по поисковому запросу.

Ограничения и предостережения

  • Поисковые запросы могут быть заблокированы. Поиск по запросу «собаки» может возвращать результаты со словом «dog» в них.
  • Результаты поиска ограничены 1000 результатами.

limit=500 Аргумент в вашем сообщении об ошибке относится к желаемому количеству возвращаемых записей, а не к желаемому количеству страниц. Способ, которым reddit выполняет разбивку на страницы, отличается от ожидаемого. В основном они отслеживают порядок сообщений, а затем, чтобы получить следующий набор сообщений (новую страницу), вы передаете идентификатор последнего сообщения в свой вызов. Я думаю, что reddit отслеживает отправителя вызова (ваш компьютер) и устанавливает ограничения на то, сколько он вернет.

Это описывает API reddit (в частности, before и after )

Вот ресурс на Python, который описывает ограничения на API reddit.


Редактировать:

Мне также непонятно, почему мы не получаем того количества результатов, о котором просили. Одна вещь, которую я заметил, это то, что 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,"amp;limit=1000amp;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,"amp;limit=1000amp;sort=commentamp;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 перестает выдавать значение для after в файле json. Это значение, которое нам нужно для того, чтобы создать новую строку поиска и получить следующую страницу. Иногда я могу заставить его возвращать 3 страницы / ~ 250 результатов, прежде чем он начнет выдавать "after": null

Комментарии:

1. Спасибо @BrianLang. Я не видел этого раньше. Однако даже с этой информацией я все еще не уверен, почему links1000 и links499 были идентичны в моем коде выше. Если ограничение равно 1000, не должно links1000 быть примерно в два раза длиннее links499 ? Мне также интересно, есть ли способ запускать последовательные проверки с 1000 результатами (первая 1000, следующая 1000, следующая 1000 и т.д.)? Я думал, что это ожидание, для которого предназначен wait_time параметр (для запуска следующих n результатов поиска после требуемого периода ожидания, поскольку только n=1000 это может быть выполнено в данный момент времени).

2. Да, это довольно странно. После просмотра кода пакета они, по сути, отправляют запросы страницы в R с некоторым промежутком времени wait_time между ними. Эти запросы являются последовательными и полагаются на переменную в возвращаемом файле json after для перехода на следующую страницу. Проблема, похоже, в том, что reddit готов обслуживать только определенное количество страниц, прежде чем after будет возвращен как null . Это, похоже, твердо на стороне reddit.