CoderCastrov logo
CoderCastrov
Python

Парсинг веб-сайтов и PDF-файлов с финансовыми отчетами конгрессменов

Парсинг веб-сайтов и PDF-файлов с финансовыми отчетами конгрессменов
просмотров
4 мин чтение
#Python

Репозиторий на Github

Члены Конгресса обязаны публично раскрывать определенные аспекты своих финансов. Эта информация является общедоступной, но, к сожалению, доступна только в неудобном формате HTML-форм или PDF-файлов. Правительство опубликовало документы, но не сделал данные машинночитаемыми. Гражданам нет простого способа агрегировать всю эту информацию и искать интересные или тревожные тенденции в отношении своих избранных представителей.

Данные могут быть запрошены, очень медленно, по следующим ссылкам:

Ссылка на Палату представителей

Ссылка на Сенат

К счастью, с помощью Python и Selenium можно парсить веб-сайты. Я использовал список ниже, чтобы найти текущих членов Конгресса, чтобы я мог получить отчеты для каждого члена.

Список текущих членов Конгресса

Отказ от ответственности

Поскольку это был один из моих первых крупномасштабных проектов, было допущено несколько ошибок. Код иногда повторяется, так как мне не удалось получить правильные значения из функций. Вероятно, я неэффективно добавляю или объединяю некоторые pandas dataframes. Здесь определенно требуется рефакторинг, но его не было сделано из-за ограничений времени. Основным приоритетом было написание работающего кода, который будет давать результаты. Веб-сайты Палаты представителей и Сената организованы по-разному, поэтому было необходимо создать отдельные парсеры и процессы для каждого из них.

Я сначала занялся данными Сената. На сайте требуется, чтобы пользователь отметил флажок, указывающий, что он понимает запреты на использование данных. Я решил использовать Selenium для автоматизации этого процесса. Пройдя эту преграду, есть несколько полей, которые можно запросить. Я взял данные Сената из репозитория theunitedstates.io, отметил "Текущий сенатор" и выбрал "Ежегодный" и "Периодические операции". В рамках этого проекта мы ищем данные, которые сообщаются один раз в год (ежегодные отчеты) и периодические обновления. Большинство PDF-файлов, которые возвращаются, являются электронно поданными, сгенерированными и машинно читаемыми (то есть я могу разобрать текст и значения), однако некоторые документы сканированы и содержат рукописные записи. Я решил оставить их без изменений и считать их вне области действия, но их можно разобрать с использованием библиотек OCR в последующем. Кажется, что большинство документов подаются электронно, что, к счастью, удобно.

Результат организован в четыре отчета: активы, обязательства, данные PTR A и данные PTR B. PTR A - это данные, поданные после ежегодных отчетов. PTR B относится к операциям супруга. Например, файл assets.csv будет содержать отчеты для всех сенаторов, которые были разобраны. В идеале, мы будем хранить эти данные в соответствующих таблицах SQL, чтобы можно было легко запросить одного сенатора и просмотреть все его активы, обязательства и другую финансовую информацию сразу.

senate_stocks.py - это основной код. Файлы csv - это результаты данных.

  • senate_stocks.py
  • assets.csv
  • liab.csv
  • ptra.csv
  • ptrb.csv

Важные заметки относительно кода на Python для Сената

  • Я игнорировал все ссылки, содержащие слово "paper", так как для их обработки потребуется оптическое распознавание символов (OCR).
  • Электронные отчеты представляют собой простые HTML-документы, которые можно обработать с помощью стандартных методов. В моем случае я использовал регулярные выражения и библиотеку BeautifulSoup.
  • Для запуска этого скрипта в облаке было необходимо использовать браузер в безголовом режиме с помощью Selenium.
  • Я использовал функции wait.until, чтобы заставить Selenium ожидать полной загрузки элементов перед попыткой выполнить клик. Также использовалась функция time.sleep, когда это было необходимо. Например: wait.until(EC.element_to_be_clickable((By.CSS_SELECTOR, xxx))).click()
  • Код создает список ссылок на отчеты каждого сенатора. Затем код проходит по каждой ссылке, извлекает текст и значения и выводит их в соответствующие CSV-файлы для каждой таблицы.
  • Начальная дата для запроса отчетов - 1 января 2017 года, записанная как '01/01/2017'. Конечная дата оставлена пустой.
  • Отчеты будут запускаться ежедневно с помощью планировщика задач cron.

Из-за ограничений по времени я не смог написать работающий скрипт для извлечения данных Палаты представителей. Я смог создать скрипт для генерации списка ссылок на отчеты, но оставлю извлечение текста и значений другим. У меня есть неполный скрипт, который я передам своему преемнику, и я использую библиотеку pdfplumber для обработки PDF-файлов. Мне удалось извлечь "сырой" текст, но потребуется значительное количество работы для его организации в удобный формат данных.

Важные заметки относительно кода на Python для парсинга данных с сайта

  • Неполный
  • Данные из PDF-файлов сохраняются в строковом формате, но все еще требуют дальнейшего разбора. Я оцениваю, что для всех полей данных потребуется еще 5-10 часов.
  • Не удалось обработать проблемы с кодировкой символов в именах представителей. Например, акценты на букве 'é' некорректно обрабатываются, что приводит к сбою запроса.
  • Я добавил некоторый код для отправки результатов на мой адрес электронной почты. Это нужно будет обновить для правильных адресов и также перенести в код для Сената.