CoderCastrov logo
CoderCastrov
Открытые данные

Загрузка общедоступных комментариев с помощью простого в использовании обертки на языке Python для API Regulations.gov

Загрузка общедоступных комментариев с помощью простого в использовании обертки на языке Python для API Regulations.gov
просмотров
10 мин чтение
#Открытые данные

Обертка на языке Python: https://github.com/willjobs/regulations-public-comments

TL;DR: Я создал обертку на языке Python для версии 4 API Regulations.gov, значительно упрощающую процесс загрузки общедоступных комментариев с Regulations.gov. Вы можете использовать ее в командной строке (без использования Python) для загрузки всех общедоступных комментариев по заданному делу или документу, или использовать немного Python для создания настраиваемого запроса (например, для загрузки всех комментариев к регулятивным актам EPA за последний месяц). Это, возможно, первая общедоступная обертка, упрощающая использование версии 4 API Regulations.gov.

В США, когда федеральные агентства предлагают новые регулятивные акты, им требуется пройти формальный процесс рассмотрения. Обычно это включает в себя опубликование Уведомления о предлагаемом регулятивном акте (NPRM), период общественных комментариев, ответы на общественные комментарии и окончательный регулятивный акт (см. это, это и это). Общественные комментарии позволяют физическим лицам и организациям предоставлять дополнительный контекст, поддерживающую информацию и мнение о предлагаемом регулятивном акте (или его отмене), хотя они не рассматриваются как "голоса" "за" или "против" регулятивного акта.

Структура данных выглядит следующим образом: все материалы, относящиеся к определенному предлагаемому регулятивному акту, содержатся в деле. Каждое дело может содержать один или несколько документов различных типов (Уведомление, Предлагаемый регулятивный акт, Регулятивный акт, Поддерживающие и связанные материалы и Другие), и общественность может оставлять комментарии к любому документу. Комментарии связаны с документом, а не с делом.

В 2003 году процесс общественных комментариев впервые стал доступен в электронном виде, что привело к значительному увеличению участия.

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

В 2012 году была создана версия 1.0 общедоступного API, который позволял пользователям программно загружать комментарии с Regulations.gov (см. документацию v1). С тех пор было выпущено несколько обновлений, и в сентябре 2020 года была выпущена версия 4 API (см. здесь). В этой последней версии API была добавлена возможность загрузки комментариев пользователями.

API очень хорошо задокументировано, с примерами и четкими спецификациями параметров и ответов. Тем не менее, есть некоторые подводные камни. Например, фильтрация по postedDate использует формат yyyy-mm-dd, но фильтрация по lastModifiedDate использует формат yyyy-mm-dd hh24:mi:ss. Кроме того, фильтр lastModifiedDate использует восточный часовой пояс, но значения, возвращаемые в ответе, находятся в формате UTC, что может вызвать несоответствие, если вы не знаете об этом и пытаетесь разбить данные на несколько запросов. Еще один пример: когда вы пытаетесь отфильтровать комментарии для конкретного документа, вы должны использовать внутренний идентификатор документа objectId (возвращаемый API), а не его documentId.

Механизм пагинации также может быть сложным: вы можете получить до 250 "элементов" (комментариев, документов или дел) за "страницу" (один запрос), и запрос может обращаться к 20 таким страницам для общего числа элементов в 5000 за запрос. Однако, что если вы запрашиваете (например) все комментарии к регулятивным актам EPA за последние два года? API ограничит вас 5000 элементами, хотя количество комментариев, безусловно, будет больше (в этом случае более 80 000). Способ обработки этого, как описано в примерах документации, заключается в следующем:

Наконец, ключ API (который можно запросить на странице документации по API) ограничен не более чем 1000 запросов в час. Обертка на языке Python обрабатывает это ограничение, обнаруживая ошибку запроса и автоматически опрашивая каждые 20 минут, пока не будут сброшены ограничения ключа API (иногда запросы сбрасываются раньше полного часа), после чего запросы продолжаются.

1000 запросов в час может показаться многим, но оказывается, что для получения текста определенного комментария вам нужно получить к нему доступ индивидуально. Описание выше о получении 250 элементов за раз дает вам только некоторую "заголовочную" информацию для каждого элемента, когда вам, скорее всего, интересна "подробная" информация. Чтобы лучше понять это, в самом низу документации по API есть раздел "Схемы", в котором перечислены все атрибуты данных, возвращаемые данным элементом. "Comment" - это то, что возвращает процесс пагинации, описанный мной выше, и он включает только agencyId, documentType, highlightedContent, lastModifiedDate, objectId, postedDate, title и withdrawn. Фактический текст комментария находится в элементе "CommentDetail" схемы, в атрибуте comment, к которому можно получить доступ по одному, используя commentId.

Моя работа началась как проект для занятия по NLP во время магистратуры, и когда мой код принял форму, я понял, что уроки, которые я извлек из использования API, могут быть полезны другим людям. Прежде чем я начал проект, я потратил немало времени на поиск на GitHub и Google, чтобы увидеть, могу ли я использовать чей-то другой код, но не нашел существующей обертки для версии 4 API. Я нашел репозиторий Sunlight Labs (теперь несуществующая организация), однако их код был последний раз обновлен в 2015 году и больше не работает. Еще один репозиторий, который я нашел, был обновлен в январе 2020 года (что означает, что он предназначен для API v3), описывает себя как "минимальный инструмент" и требует ручного редактирования файла Python для загрузки комментариев по заданному идентификатору дела. Так что, поскольку не было готового кодовой базы, ориентированной на API v4, я создал свою собственную.

Быстрый старт с командной строки

Самый простой способ начать работу с этим кодом - использовать командную строку. Клонируйте весь репозиторий или скачайте comments_downloader.py. Для работы кода требуется Python 3; вам также понадобится библиотека pandas (если у вас ее еще нет, выполните pip install pandas, или conda install pandas, если у вас установлен Anaconda или miniconda). Подход с командной строкой позволяет загрузить все комментарии для указанного документа (указанного с помощью documentId) или дела (для всех его документов и указанного с помощью docketId). В дополнение к идентификатору, вам нужно будет указать ваш ключ API, который вы можете получить на странице документации Regulations.gov. Обратите внимание: все вхождения DEMO_KEY в этом документе следует заменить на ваш ключ API. Затем комментарии будут загружены в CSV-файл с именем в формате ВАШ-ИД-ЗДЕСЬ.csv в текущем каталоге. Например:

# загрузить все комментарии для дела FDA-2021-N-0270 (для всех его документов)
python comments_downloader.py --key DEMO_KEY --docket FDA-2021-N-0270

Загрузка комментариев для дела с идентификатором FDA-2021-N-0270...
2021-07-18 16:26:30: Получение документов, связанных с делом FDA-2021-N-0270...

Найдено 1 документов...
2021-07-18 16:26:31: Запись 1 записей в document_headers_162630.csv...Готово
2021-07-18 16:26:31: Удаление дубликатов в CSV...
2021-07-18 16:26:31: Готово. Удалено 0 дублирующихся строк из document_headers_162630.csv.
2021-07-18 16:26:31: Завершено: собрано примерно 1 документов

Готово----------------

******************************
2021-07-18 16:26:31: Получение комментариев для документа FDA-2021-N-0270-0001...

2021-07-18 16:26:31: Получение идентификатора объекта для документа FDA-2021-N-0270-0001...Получено (0900006484a930da)
2021-07-18 16:26:31: Получение заголовков комментариев, связанных с документом FDA-2021-N-0270-0001...

Найдено 188 комментариев...
2021-07-18 16:26:31: Запись 188 записей в comment_headers_162631.csv...Готово
2021-07-18 16:26:31: Удаление дубликатов в CSV...
2021-07-18 16:26:32: Готово. Удалено 0 дублирующихся строк из comment_headers_162631.csv.
2021-07-18 16:26:32: Завершено: собрано примерно 188 комментариев

Завершено получение идентификаторов комментариев----------------

2021-07-18 16:26:32: Получение комментариев, связанных с документом FDA-2021-N-0270-0001...

2021-07-18 16:26:32: Сбор деталей для 188 комментариев...
2021-07-18 16:27:03: Запись 188 записей в FDA-2021-N-0270.csv...Готово
2021-07-18 16:27:03: Завершено: собрано 188 комментариев

Завершено получение всех 188 комментариев для документа FDA-2021-N-0270-0001----------------

ГОТОВО получение всех 188 комментариев из 1 документа(ов) для дела FDA-2021-N-0270----------------

Аналогично, для загрузки всех комментариев к одному документу вы должны указать --document в командной строке и идентификатор документа (тот, который вы видите в URL):

# загрузить все комментарии для документа FDA-2009-N-0501-0012
python comments_downloader.py --key DEMO_KEY --document FDA-2009-N-0501-0012

Загрузка комментариев для документа с идентификатором FDA-2009-N-0501-0012...
2021-07-20 20:11:09: Получение идентификатора объекта для документа FDA-2009-N-0501-0012...Получено (09000064847f0822)
2021-07-20 20:11:09: Получение заголовков комментариев, связанных с документом FDA-2009-N-0501-0012...

Найдено 10 комментариев...
2021-07-20 20:11:10: Запись 10 записей в comment_headers_201109.csv...Готово
2021-07-20 20:11:10: Удаление дубликатов в CSV...
2021-07-20 20:11:10: Готово. Удалено 0 дублирующихся строк из comment_headers_201109.csv.
2021-07-20 20:11:10: Завершено: собрано примерно 10 комментариев

Завершено получение идентификаторов комментариев----------------

2021-07-20 20:11:10: Получение комментариев, связанных с документом FDA-2009-N-0501-0012...

2021-07-20 20:11:10: Сбор деталей для 10 комментариев...
2021-07-20 20:11:12: Запись 10 записей в FDA-2009-N-0501-0012.csv...Готово
2021-07-20 20:11:12: Завершено: собрано 10 комментариев

Завершено получение всех 10 комментариев для документа FDA-2009-N-0501-0012----------------

Завершено получение всех 10 комментариев для документа FDA-2009-N-0501-0012----------------

Важно отметить, что в обоих примерах возвращается небольшое количество комментариев. Если дело или документ, который вы запрашиваете, имеет более 1000 комментариев, вы достигнете предела запросов вашего ключа API и должны будете подождать до часа, чтобы ваш лимит запросов сбросился. Код автоматически обрабатывает это для вас, ожидая и проверяя каждые 20 минут, чтобы узнать, получили ли вы еще 1000 запросов. Возможно связаться с Helpdesk, чтобы получить до 2000 запросов в час и до двух ключей на пользователя.

Вероятно, командная строка будет достаточна для 90% случаев использования, так как люди часто интересуются только комментариями к определенному делу. Однако для настраиваемых запросов, например, для загрузки комментариев для множества дел одновременно или для получения результатов в базе данных SQLite (.db) вместо CSV, вы можете использовать Python.

Пользовательские запросы с использованием Python

Jupyter-ноутбук Examples.ipynb в репозитории демонстрирует, как использовать comments_downloader.py; это хорошее место для получения дополнительных примеров. Обратите внимание, что для использования этого кода требуется библиотека pandas.

Первый шаг в использовании кода - импортировать его и создать новый экземпляр класса CommentsDownloader (замените DEMO_KEY на ключ API, который вы получили на https://open.gsa.gov/api/regulationsgov/#getting-started:

Пример 1:

В первом примере мы можем загрузить наши комментарии как в базу данных SQLite, так и в CSV, указав собственные имена файлов для каждого из них (в качестве альтернативы, вы также можете экспортировать только в SQLite или CSV):

Результаты будут такими же, как если бы вы использовали командную строку. Есть несколько преимуществ использования базы данных SQLite вместо CSV: вы можете выполнять SQL-запросы (включая объединения и т. д.), вы можете добавлять ограничения, и гарантируется, что не будет проблем с символами в строках комментариев, которые могут повлиять на импорт CSV. (Код делает все возможное, чтобы избежать этой проблемы с CSV: символы кавычек удваиваются, а переносы строк заменяются пробелом, чтобы каждая строка в CSV была одной "записью"). Еще одно большое преимущество - вы можете хранить данные из дел, документов и комментариев в одном месте. Например, при загрузке всех комментариев по определенному делу, информация заголовка о документах будет храниться в таблице documents_header, заголовки комментариев - в таблице comments_header, а подробности о каждом комментарии (включая текст комментария) - в таблице comments_detail. Это в отличие от вывода в командной строке, который будет выводить только эквивалент таблицы comments_detail в CSV. Полная схема базы данных доступна здесь.

Пример 2

Для загрузки всех комментариев, связанных с несколькими документами, хорошо подходит следующая структура кода (обратите внимание, что если бы мы указали имя файла CSV, все комментарии документов были бы содержатся в одном файле CSV):

Примечание

Строки кода выше абстрагируют много деталей. Обычно нет прямого способа перейти от идентификаторов документов (docketId) к комментариям, потому что доступные фильтры в API позволяют фильтровать комментарии только по документам. Поэтому сначала вы бы использовали идентификаторы документов (docketId) для запроса документов каждого дела, используя конечную точку documents (вместо dockets в приведенном выше использовании gather_headers):

Затем вы бы использовали заголовки документов, загруженные в файл EPA_water_documents.csv, чтобы запросить связанные с ними комментарии, но сначала вам нужно получить objectId каждого документа из этого файла. Это связано с тем, что API фильтрует комментарии по objectId документа, а не по его documentId (я предполагаю, что это связано с проблемой данных на сервере, где фактически есть несколько документов с одним и тем же documentId; я видел странное поведение для некоторых редких documentId). Затем вы бы использовали эти objectId для получения комментариев, аналогично приведенному выше:

Наконец, имея эти заголовки комментариев, вы могли бы использовать каждый commentId в EPA_water_comments_header.csv, чтобы собрать полные данные для каждого комментария, обратившись к конечной точке "Details":

Обратите внимание, что если бы вы использовали SQLite, а не четыре отдельных файлов CSV, у вас была бы одна база данных, в которой все эти данные хранились бы в одном месте.

Пример 3

Наконец, немного более сложный пример с пользовательским запросом: предположим, мы хотим загрузить все комментарии, связанные с документами EPA, содержащими термин "вода" и размещенными между 1/1/2017 и 31/12/2020. Наш первый шаг - получить заголовки документов с searchTerm "вода" и lastModifiedDate между 1/1/2017 и 31/12/2020:

Вышеуказанные результаты загружают 353 записи (документы) в файл EPA_water_dockets.csv. Теперь все, что вам нужно сделать, это:

Для получения дополнительной информации о Regulations.gov и его API вы можете посетить официальную документацию или ознакомиться с блог-постами, которые я написал во время моей магистратуры. В частности, пост 1 содержит раздел о веб-интерфейсе и примеры комментариев, а пост 2 дает гораздо больше деталей, чем этот пост, о API и некоторых наблюдениях. Кроме того, вы можете ознакомиться с документацией для этого кода.


Опубликовано на https://willjobs.com 22 июля 2021 года.