CoderCastrov logo
CoderCastrov
Парсер

Анализ выступлений Дутерте с использованием NLP

Анализ выступлений Дутерте с использованием NLP
просмотров
6 мин чтение
#Парсер

Часть 1: Парсинг выступлений президента Дутерте

Учитывая текущую ситуацию с COVID-19 в разных странах, срочность для их правительств взять на себя и решить пандемию еще более повысилась. История не отличается и здесь, на Филиппинах, поскольку частота пресс-конференций президента Родриго Дутерте, адресованных филиппинскому народу, возросла. Это вдохновило меня на работу над личным проектом, который будет анализировать его выступления на протяжении многих лет с использованием обработки естественного языка (NLP).

Конечно, прежде чем я смогу проанализировать его выступления, мне нужно собрать их. Это Часть 1 анализа выступлений Дутерте, которая будет сосредоточена на парсинге его выступлений. Последующие статьи этой серии будут посвящены их анализу с использованием NLP. Для кода, который я написал, ознакомьтесь с моим репозиторием на GitHub - хотя я признаю, что мой код здесь немного беспорядочный - и оставьте комментарии или предложения, если у вас есть. Я также в конечном итоге обновлю свою README с инструкциями по запуску программ на Python.

К счастью для меня, Президентское управление по коммуникациям (PCOO) страны публикует его выступления на своем веб-сайте, по крайней мере, до определенного момента (на странице указано, что есть 31 страница, но если вы перейдете за определенный номер страницы, вы получите ошибку "страница не найдена"). Таким образом, выступления, которые я собрал, были только с 2020 по 2018 год.

Для парсинга выступлений я в основном использовал библиотеки Python BeautifulSoup4 и requests, а также использовал pandas для структурирования набора данных, python-dotenv для переменных среды и несколько библиотек для извлечения текста из PDF-файлов.



Парсинг веб-сайта PCOO

Изначально, когда я попытался использовать библиотеку requests для выполнения GET-запроса на веб-сайт PCOO, я постоянно получал ошибку подключения. После дальнейшего исследования я выяснил, что это происходит потому, что некоторые веб-сайты, включая PCOO, обычно не любят, когда роботы сканируют их. Вы можете увидеть это, перейдя на их robots.txt, где указаны следующие настройки, направленные на запрет доступа роботов.

User-Agent: *
Disallow:

Поэтому мне пришлось выполнить несколько дополнительных шагов, чтобы обойти настройки против роботов и предотвратить помещение моего IP-адреса в черный список в качестве предосторожности. Во-первых, мне нужно было скрыть свою робот-программу под видом человека, прикрепив агент пользователя к каждому запросу, который я хранил в файле .env (отсюда и установка python-dotenv). Во-вторых, было бы слишком очевидно, если один IP-адрес делал GET-запросы к веб-сайту с быстротой пулемета, поэтому я распределил каждый запрос на 15 секунд с помощью time.sleep, чтобы это выглядело более естественно. Признаюсь, что это значительно увеличило время парсинга, но позже я объясню, как я смог значительно ускорить этот процесс.

Выше приведен фрагмент основной программы, который находится в файле 01_scraper.py и парсит речи на каждой странице веб-сайта. Каждая страница содержит 20 речей, каждую из которых я называю row в своей программе. Каждая речь перенаправляет вас на страницу с подробностями речи (пример), содержащую аудио, полный текст и, возможно, видео пресс-конференции. Полный текст перенаправляет вас на PDF-файл с текстом речи (пример).

Я создал функцию с названием extract_page в моем файле scraper_functions.py, которая обрабатывает каждую строку с использованием вышеуказанной процедуры и возвращает словарь, содержащий заголовок, дату речи и извлеченный текст.

Следующий вопрос заключается в том, как извлечь текст из PDF-файлов?

Извлечение PDF: Какую библиотеку использовать?

Чтобы сократить время парсинга в случае, если я захочу попробовать другие библиотеки для работы с PDF, я сохранил PDF-файлы в своем репозитории. Таким образом, мне не пришлось снова парсить веб-сайт PCOO. После этого я нашел четыре библиотеки Python для извлечения текста из PDF:

Изначально я использовал PyPDF2, но для некоторых выступлений он мог извлекать только пустые строки, так что результатом было что-то вроде \n\n\n\n\n\n\n\n. В результате я создал функцию для проверки, возвращает ли извлеченный текст строку без слов с использованием регулярных выражений. Если функция возвращала True, то я использовал slate3k для извлечения текста из этого выступления. Тем не менее, у библиотеки иногда были неправильные результаты, такие как полное пропускание частей выступления и странное разделение каждой буквы текста для некоторых выступлений (т а к и м). Тем не менее, я собрал все результаты, используя PyPDF2 и slate3k, в один csv файл.

Затем я попробовал tika, потому что я слишком разочаровался предыдущими результатами, когда пытался анализировать данные, и это сработало прекрасно. Так прекрасно, что я даже не успел попробовать PDFPlumber (поэтому, если вы использовали его раньше, дайте мне знать, насколько он функционален!). Никакие ошибки не были обнаружены при извлечении всего, поэтому процесс использования этой библиотеки был практически безупречным. Я решил использовать результаты tika вместо остальных трех пакетов для моего анализа.

Многопроцессорность

Я упомянул выше, что для каждой речи было два этапа парсинга: страница с подробностями речи и страница с PDF-транскриптом, что составляет более 30 секунд парсинга на каждую речь. Учитывая, что на каждой странице есть 20 речей, нам требуется более 10 минут (плюс дополнительные 15 секунд для парсинга самой страницы) для извлечения всех речей на одной странице. Было около 21 действительной страницы, поэтому в целом для извлечения всех речей потребуется теоретически около 210 минут или примерно 3,5 часа. Однако на самом деле мне понадобилась около недели, чтобы завершить парсинг из-за многочисленных ошибок, возникающих при использовании PyPDF2 и slate3k.

Это побудило меня изучить многопроцессорность, чтобы ускорить весь процесс, используя в качестве инструмента извлечения PDF tika, и это сработало чудеса.

Поскольку я не смог сохранить PDF-файлы локально во время первой попытки, мне пришлось перезапустить весь процесс парсинга. Но с помощью многопроцессорности я мог запустить несколько рабочих процессов для обработки одного и того же набора данных (в данном случае 20 речей на странице) параллельно, а не последовательно.

Используя объект Pool, представляющий пул рабочих процессов, я смог отобразить данные (20 строк данных на странице) на рабочие процессы, и рабочие процессы выполняли функцию extract_page параллельно. После завершения всех рабочих процессов список из 20 словарей, возвращаемых функцией, был добавлен в рабочий DataFrame pandas. Я также добавил текстовый файл для регистрации каждой речи при их обработке (что я также делал для первой попытки).

Я сравнил общее время, затраченное на парсинг одной страницы для первой и второй попыток, используя мой scrape_logs.txt, и разница была заметна. Для первой попытки требовалось 13-20 минут, чтобы завершить одну страницу, в то время как для моей второй попытки с использованием многопроцессорности потребовалось всего 4-5 минут. Это также благодаря гладкой работе библиотеки tika, где я не столкнулся с ошибками при извлечении текста (хотя я столкнулся с этой странной ошибкой ограничения рекурсии, связанной с многопроцессорностью, которую я исправил, добавив sys.recursionlimit(10000)). В целом, вторая попытка с использованием многопроцессорности длилась всего около 1,5 часов!

Я также был удовлетворен самим извлечением PDF, видя, что полученные тексты с помощью tika содержат только незначительные ошибки. Поэтому я решил не продолжать использовать PDFPlumber.


В целом, я успешно спарсил веб-сайт PCOO, чтобы собрать речи Дутерте и объединить их в один файл csv, дополнительно ускорив весь процесс с помощью многопроцессорности.

Для части 2 (и, возможно, части 3) я попытаюсь проанализировать эти данные, которые я собрал, с использованием инструментов NLP, таких как NLTK и TF-IDF/N-граммы. Еще раз, пожалуйста, ознакомьтесь с моим репозиторием на GitHub и оставьте комментарии или предложения ниже, если у вас есть какие-либо! Я буду очень благодарен.