Reddit - один из самых популярных интернет-форумов для обсуждения, обмена контентом и многого другого. В 2019 году Reddit вырос почти до 430 миллионов пользователей в месяц. Сайт содержит сотни групп, называемых субреддитами, которые содержат сотни тысяч сообщений и комментариев. Reddit - это огромный источник естественного языка, внешних ссылок и других данных. Настоящий вопрос в том, как вы добываете эти данные?

В отличие от других веб-сайтов социальных сетей, Reddit предлагает наблюдательный API, который позволяет просматривать субреддиты, сообщения и комментарии в формате JSON без аутентификации. Этот API используется только для чтения данных с периодическими ограничениями на количество вызовов API, которые можно сделать. Его нельзя использовать для взаимодействия или отправки данных на Reddit. Однако API наблюдений предоставляет очень удобный способ извлечения данных из Reddit. В этой статье будет подробно описано, как выполнять вызовы API и форматировать данные, добытые с помощью Python. Такое же поведение и реализации могут быть созданы для любого языка программирования, который, по крайней мере, предоставляет способ делать HTTP-запросы и анализировать строки json.

Заявление об ограничении ответственности: это руководство официально не одобрено и не написано Reddit. Не используйте какой-либо Reddit API способом, который нарушает положения и условия Reddit. Дополнительную информацию о пользовательском соглашении Reddit можно найти здесь.

Списки, ресурсы и URL-адреса

Reddit API организует субреддиты, сообщения, ссылки, комментарии и другие компоненты сайта в объекты, называемые списками. Списки - это интерфейс над контентом, который может изменяться очень часто, где использование разбивки на страницы не будет масштабируемым и слишком сложным. Если вы думаете о листинге как о целом субреддите, в листинге могут быть миллионы дочерних объектов. Следовательно, вызовы API возвращают фрагменты списков. Срез листинга состоит из следующих компонентов:

  • count: количество предметов, которые уже были просмотрены в листинге
  • до / после: точка фиксации, указывающая, где в списке существует срез.
  • limit: указанное количество, указывающее максимальное количество элементов, которое может содержать данный фрагмент листинга.

Списки могут содержать шесть различных типов объектов. Эти дочерние объекты - это сообщения, ссылки, комментарии и пользователи, которые в первую очередь составляют субреддит. Каждый объект имеет уникальное «полное имя». Это полное имя имеет формат <type>_<UID>, где тип может быть одним из следующих:

В этом руководстве мы сосредоточимся в первую очередь на ссылках и комментариях. Эти два типа ресурсов содержат большую часть языковых данных в Reddit.

Самый первый шаг к доступу к API Reddit - это вызов API. Это можно сделать с помощью любой HTTP-библиотеки, поддерживающей запросы GET. Следующий код примет простое имя субреддита и вернет объект JSON, представляющий список субреддита.

Чтобы сделать вызов API в Python, мы можем использовать urllib.request.urlopen. Эта функция предоставляет удобную оболочку для HTTP-методов нижнего уровня для выполнения простого запроса GET с одной строкой URL-адреса. После вызова urlopen необходимо проверить статус, чтобы убедиться, что он не достиг 404 или какой-либо ошибки. Любой субреддит доступен как api через расширение/.json. Фактически, это основная разница между доступом к версии html и версии json. Поскольку к URL-адресу добавлен/.json, мы можем предположить, что содержимое ответа будет json, и загрузить его через json.loads. Этот процесс открытия URL-адреса и его синтаксического анализа для json будет служить базовым действием для потоков данных, описанных в этой статье.

Субреддиты и заголовки

Во-первых, давайте посмотрим на ответ API на вызов субреддита. Поскольку ответ содержит большие объекты с множеством полей, мы будем обсуждать части ответа за раз. Это первый пример для science субреддита, одного из крупнейших на сайте.

В самом верху объекта ответа есть поле «вид», указывающее, что это список, а затем поле данных. Свойство modhash - это токен, который Reddit использует для предотвращения CSRF, давайте просто проигнорируем это. Реально интересным компонентом этого ответа является массив для поля «children», который представляет собой массив объектов, представляющих сообщения. Несмотря на то, что это тип «t3», ссылка означает либо сообщение, URL-адрес, который является сообщением, либо ссылку на изображение, которое является сообщением. В Reddit вы можете сделать сообщение, которое представляет собой просто ссылку и заголовок или текст с заголовком.

Поле «selftext» представляет текст в теле сообщения. Если это пустая строка, это означает, что это не текстовое сообщение, это сообщение со ссылкой. Поля вроде «title» и «subreddit_name_prefixed» должны быть простыми. Другие важные поля следующие

Поле «name» объекта сообщения указывает его уникальный идентификатор, который мы позже будем использовать для вызова API и извлечения комментариев. Поле «оценка» - это чистый результат голосов «за» и «против» для определенного сообщения. Точно так же соотношение голосов "за" дает вам представление о соотношении голосов "за" и "против". Created_utc - это время создания сообщения, а «num_comments» - количество комментариев к сообщению.

Первым примером интеллектуального анализа данных здесь будет использование субреддита, анализ текста его заголовка, подсчет слов, а затем отображение сопоставления наиболее часто используемых слов в заголовках этого субреддита. Для этого нам нужно будет сделать запрос GET к API, а затем извлечь сообщения. Посты существуют как подобъекты в «дочернем» массиве данных листинга. Кроме того, нам нужны только t3 ссылки на ресурсы, поскольку это сообщения. Вот полная реализация скрипта:

В приведенном выше коде harvest_posts выполняет вызовы API и извлекает объекты сообщений. Затем count_title_words просматривает сообщения, разбивает заголовок на слова и вставляет количество слов в словарь. Это создает сопоставление слова с количеством раз, которое оно встречается во всех заголовках в подпрограмме Reddit. Наконец, код просматривает созданный словарь и печатает вхождения каждого слова.

Пример вывода вышеуказанной программы можно найти ниже. Заметьте, это не лучший способ выражения моих слов. Обработка знаков препинания отсутствует, поэтому fountain и fountain, будут считаться двумя отдельными словами. Тем не менее, этого достаточно, чтобы получить представление о том, как частота слов проявляется в конкретном субреддите.

В идеале, вызывая API и ожидая ответа с определенными ключами и полями, важно проверять любой объект, с которым вы работаете. Хотя обычно может быть гарантирован формат данных, например json или xml, иногда API меняют свои схемы или изменяют конкретное написание своих полей. Это просто более чистый и качественный метод проверки того, что ответ от API имеет ожидаемую вами схему. Ниже представлен простой способ сделать это:

Каждый API имеет ограничение скорости, которое, как только вы его достигнете, вам нужно подождать некоторое время, прежде чем ваш запрос будет принят и обработан. В Reddit существует более низкий предел для API наблюдения, чем для API OAuth. Однако данные интеллектуального анализа данных обычно не требуют высокого ограничения скорости. Ни один из описанных здесь методов никоим образом не позволяет использовать данные в реальном времени. Они предназначены для загрузки и поиска или запроса данных на естественном языке Reddit. Один из примеров дроссельной заслонки ограничения скорости выглядит следующим образом:

Предупреждение: не пытайтесь нарушить ограничения API Reddit.

Комментарии

Другой важный источник данных на Reddit - это комментарии. Комментарии на самом деле содержат гораздо большую часть данных, поскольку комментариев намного больше, чем сообщений в большинстве крупных подреддитов. Комментарии можно добывать аналогично тому, как добываются сообщения, с небольшими изменениями. Во-первых, необходимо получить комментарии из API к определенным сообщениям. Вы можете сделать это через сообщения id. Это поле присутствует в поле данных объекта сообщения, обсуждаемого в предыдущем разделе, оно принимает форму form"id": "hqr6yi",. Этот идентификатор вместе с сабреддитом, которому он принадлежит, можно использовать для создания немного другого URL-адреса json для запроса GET. Это будет через функцию, как показано ниже,

Разница с комментариями заключается в том, что структура списка, который вы получаете от API, отличается от структуры вызова сабреддита. При запросе комментариев к сообщению вы получаете список, в котором первый дочерний объект - это t3 объект, представляющий сам пост, а остальные объекты - это t1 объекты, представляющие комментарии к сообщению. Объекты комментариев t1 более краткие, чем объекты сообщений. Весь объект комментария выглядит следующим образом:

Текст комментария сохраняется в поле body. Помимо текста комментария, есть много данных, с которыми можно сопоставить текст для некоторого глубокого анализа. Поле ups указывает, сколько голосов было получено. Вы также можете увидеть, были ли комментарии удалены, прикреплены, их общий балл и многое другое.

Кроме того, если вы хотите создать визуализированную веб-страницу с верхними комментариями, собранными из разных сообщений, вы можете использовать поле body_html, чтобы отобразить их внутри визуализированного html-документа. Или, если вы хотите создать архив комментариев Reddit, вы можете просто просмотреть несколько фрагментов списка, получить каждый комментарий и сохранить его в файле csv или json. Возможности безграничны.