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

Веб-парсинг - это метод, используемый для извлечения больших объемов данных с веб-сайтов, при котором данные извлекаются и сохраняются в локальном файле на вашем компьютере или в базе данных в формате таблицы (электронной таблицы). - WebHarvy

Как правило, веб-парсинг включает доступ к многочисленным веб-сайтам и сбор с них данных. Однако мы можем ограничиться сбором большого количества информации из одного источника и использовать его как набор данных. В этом конкретном примере мы исследуем Википедию. Я также объясню основы HTML, которые нам понадобятся. Полный проект доступен в виде записной книжки в репозитории Github Web Scraping using Python.

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

Это статья из 2 частей. В этой первой части мы рассмотрим, как получить данные с веб-сайта с помощью BeautifulSoup, а во второй части мы очистим собранный набор данных.

Определить содержание

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

Здесь мы объединим данные с этих двух веб-страниц в один набор данных.

  1. Список стран. При переходе на первую страницу мы извлекаем список стран, их население и процент населения мира.
  2. Страна. Затем мы перейдем на страницу каждой страны и получим информацию, включая общую площадь, процент воды и ВВП (номинальный).

Таким образом, наш окончательный набор данных будет включать информацию о каждой стране.

Основы HTML

Каждая веб-страница, которую вы просматриваете в своем браузере, на самом деле структурирована на языке гипертекстовой разметки (HTML). Он состоит из двух частей: заголовок, который включает заголовок и любые операции импорта для стилизации и JavaScript, и тело, которое включает контент, отображаемый в виде веб-страницы. Нас интересует основная часть веб-страницы.

HTML состоит из тегов. Тег описывается открывающей < и закрывающей > угловой скобкой с именем тега внутри нее в качестве начала, в то время как он отмечает конец, если после открывающей угловой скобки стоит косая черта /. Например, <div></div>, <p>Some text</p> и т. Д.

Есть два прямых способа получить доступ к любому элементу (тегу), присутствующему на веб-странице. Мы можем использовать id, который является уникальным, или мы можем использовать класс, который может быть связан с несколькими элементами. Здесь мы видим, что <div> имеет атрибут id as base, который действует как ссылка на этот элемент, в то время как все ячейки таблицы, отмеченные td, имеют один и тот же класс с именем data.

Обычно полезные теги включают:

  1. <div>: Всякий раз, когда вы включаете определенный контент, вы заключаете его вместе в один объект. Он может выступать в качестве родительского для множества различных элементов. Таким образом, если здесь будут применены некоторые изменения стиля, они также отразятся на его дочерних элементах.
  2. <a>: ссылки описываются в этом теге, где веб-страница, которая будет загружена при нажатии этой ссылки, упоминается в ее свойстве href.
  3. <p>: этот тег используется всякий раз, когда некоторая информация должна отображаться на веб-странице в виде блока текста. Каждый такой тег отображается как отдельный абзац.
  4. <span>: Когда информация должна отображаться в строке, мы используем этот тег. Когда два таких тега размещаются рядом, они появляются в одной строке, в отличие от тега абзаца.
  5. <table>: Таблицы отображаются в HTML с помощью этого тега, где данные отображаются в ячейках, образованных пересечением строк и столбцов.

Импортировать библиотеки

Сначала мы импортируем необходимые библиотеки, а именно numpy, pandas, urllib и BeautifulSoup.

  1. numpy: очень популярная библиотека, которая делает операции с массивами очень простыми и быстрыми.
  2. pandas: Это помогает нам преобразовывать данные в табличную структуру, чтобы мы могли манипулировать данными с помощью множества эффективно разработанных функций.
  3. urllib: мы используем эту библиотеку, чтобы открыть URL-адрес, из которого мы хотим извлечь данные.
  4. BeautifulSoup: Эта библиотека помогает нам получить структуру HTML страницы, с которой мы хотим работать. Затем мы можем использовать его функции для доступа к определенным элементам и извлечения соответствующей информации.

Понять данные

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

В функции getHTMLContent() мы передаем URL. Здесь мы сначала открываем URL-адрес с помощью метода urlopen. Это позволяет нам применять библиотеку BeautifulSoup для получения HTML с помощью парсера. Хотя доступно множество парсеров, в этом примере мы используем html.parser, который позволяет нам анализировать файлы HTML. Затем мы просто возвращаем результат, который затем можем использовать для извлечения наших данных.

Мы используем эту функцию, чтобы получить HTML-контент для страницы Википедии со списком стран. Мы видим, что страны представлены в таблице. Итак, мы используем метод find_all(), чтобы найти все таблицы на странице. Параметр, который мы передаем внутри этой функции, определяет возвращаемый элемент. Поскольку нам требуются таблицы, мы передаем аргумент как table, а затем перебираем все таблицы, чтобы определить нужную.

Мы печатаем каждую таблицу с функцией prettify(). Эта функция делает вывод более читаемым. Теперь нам нужно проанализировать вывод и посмотреть, в какой таблице есть данные, которые мы ищем. После тщательного изучения мы видим, что таблица с классом wikitable sortable содержит нужные нам данные. Таким образом, наш следующий шаг - получить доступ к этой таблице и ее данным. Для этого мы будем использовать функцию find(), которая позволяет нам не только указывать элемент, который мы ищем, но также указывать его свойства, такие как имя класса.

Таблица в HTML состоит из строк, обозначенных тегами <tr></tr>. В каждой строке есть ячейки, которые могут быть заголовками, определенными с помощью <th></th>, или данными, определенными с помощью <td></td>. Таким образом, чтобы получить доступ к веб-странице каждой страны, мы можем получить ее ссылку из ячеек в столбце страны таблицы (второй столбец). Итак, мы перебираем все строки в таблице и считываем данные второго столбца в переменной country_link. Для каждой строки мы извлекаем ячейки и получаем элемент a во втором столбце (нумерация в Python начинается с 0, поэтому второй столбец будет означать cell[1]). Наконец, печатаем все ссылки.

Ссылки не включают базовый адрес, поэтому всякий раз, когда мы открываем любую из этих ссылок, мы добавляем https://en.wikipedia.org в качестве префикса.

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

На странице каждой страны справа есть информационное поле с девизом, названием, ВВП, территорией и другими важными характеристиками. Итак, сначала мы определили имя этого поля с помощью тех же шагов, что и раньше, и это была таблица с классом как infobox geography vcard. Затем мы определяем переменную additional_details для сбора всей информации, которую мы получим с этой страницы, в массиве, который мы затем можем добавить к списку набора данных стран.

Когда мы входим в режим проверки браузера Chrome (щелкните правой кнопкой мыши в любом месте и выберите параметр Inspect) на странице страны, мы можем просмотреть классы для каждого заголовка в таблице. Нас интересуют четыре поля: Площадь - Общая площадь, Водные ресурсы (%) и ВВП (номинальный) - Всего, На душу населения.

Мы можем легко сделать вывод, что заголовки Area и GDP (nominal) имеют классы mergedtoprow, а данные, которые мы хотим извлечь, имеют классы mergedrow или mergedrowbottom. Но мы не можем напрямую обратиться к какому-либо элементу данных, так как порядок их возникновения меняется в зависимости от страны. В некоторых странах может отсутствовать конкретное поле, и mergedrow для total area может быть 6-м, а для некоторых других - 7-м. Таким образом, нам нужно сначала увидеть текст для mergedtoprow, и если он соответствует либо площади, либо ВВП (номинальному), мы должны прочитать и собрать эти данные.

Кажется достаточно простым, но когда я попробовал, я сразу же увидел проблему, поскольку water (%) для некоторых стран было больше 100. Это невозможно, и, следовательно, мы, должно быть, чего-то упускаем. Тогда я понял, в чем проблема. Видите ли, если мы прочитаем два значения после заголовка «Площадь» и значение воды отсутствует, мы неправильно прочитаем первое значение численности населения, что приведет к неверным данным. В результате нам нужно убедиться, что когда заголовок Population идентифицирован, мы перестаем читать значения.

Теперь мы можем просто добавить все наши знания к функции getAdditionalDetails(). Мы определяем переменную read_content, чтобы отмечать, читаем мы следующее значение или нет. Здесь мы используем три типа функций, помимо описанных ранее:

  1. get(): Это позволяет нам не только найти, но и получить ссылку на конкретный элемент.
  2. get_text(): получает значение, которое присутствует в открывающем и закрывающем тегах элемента.
  3. strip(): удаляет любые дополнительные начальные и конечные пробелы, которые могут присутствовать в тексте. Мы также можем указать любое конкретное значение, которое мы могли бы пожелать удалить, например, в нашем случае символ новой строки \n.

Обходя все строки в таблице, итератор проверяет, соответствует ли текущая строка заголовку, соответствующему Площадь или GDP (номинальный), и начинает чтение. В режиме чтения он проверяет, является ли новый элемент «Общая площадь» или «Всего», и если да, он считывает его и продолжает считывать, чтобы при следующем прогоне считать воду (%) или ВВП на душу населения соответственно.

Мы используем try и except, чтобы гарантировать, что даже если мы пропустим определенные значения, весь наш процесс не закончится. Это еще один урок, который я усвоил, просматривая полный список стран. В некоторых странах нет всей необходимой нам информации, или, возможно, мы не можем найти таблицу с нужным названием. В таком случае наш процесс может выдать ошибку, которую мы должны уловить, чтобы вернуть пустой массив и позволить процессу продолжиться для других стран.

Создать набор данных

Наконец, теперь мы знаем, какую информацию нам нужно собирать, а также как ее собирать.

Сначала мы читаем каждую строку таблицы из списка стран и собираем название каждой страны, численность населения и% населения мира. Затем мы используем ссылку, чтобы получить все дополнительные сведения, включая общую площадь, воду (%), общий ВВП и ВВП на душу населения. Если, однако, дополнительная информация меньше 4, значит, информация для этой страны отсутствует, и мы не используем эти данные. В противном случае мы добавляем всю эту информацию в массив data_content, который компилируется в dataset фрейм данных.

Затем мы читаем заголовки таблицы и добавляем заголовки для 4 дополнительных столбцов. Они действуют как заголовки для нашего набора данных, который мы экспортируем в файл .CSV, который можно найти здесь.

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

Надеюсь, вам понравилась моя статья. Пожалуйста, не стесняйтесь обращаться к нам и делиться своими мыслями.