Некоторое время назад я читал ветку на сабреддите LearnML. Который OP необходимо для очистки данных веб-страницы для его проекта ML.

Люди в ветке дали хорошие ответы. В основном это было узнать, как использовать beautifulsoup и селен.

Но ОП может не знать, как относиться к его проекту машинного обучения. Если у него нет опыта работы с этими библиотеками.

Я использовал BeautifulSoup и Selenium для некоторых своих научных проектов с данными. Хотя это и не самые сложные задачи, с ним справились.

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

Причина, по которой мы хотим преобразовать его в фрейм данных. Разве что большинство библиотек ML могут обрабатывать фреймы данных pandas и могут быть отредактированы для вашей модели с минимальными изменениями.

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

Я собираюсь просмотреть таблицу самых просматриваемых спортсменов в Википедии.

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

Мы будем использовать BeautifulSoup с помощью запросов и библиотеки регулярных выражений.

from bs4 import BeautifulSoup
import requests
import re
import pandas as pd

Здесь мы извлекаем HTML-код с веб-страницы:

website_url = requests.get('https://en.wikipedia.org/wiki/Wikipedia:Multiyear_ranking_of_most_viewed_pages').text
soup = BeautifulSoup(website_url, 'lxml')
print(soup.prettify())
</a>
</li>
<li id="footer-places-disclaimer">
<a href="/wiki/Wikipedia:General_disclaimer" title="Wikipedia:General disclaimer">
Disclaimers
</a>
</li>
<li id="footer-places-contact">
<a href="//en.wikipedia.org/wiki/Wikipedia:Contact_us">
Contact Wikipedia
</a>
</li>
<li id="footer-places-mobileview">
<a class="noprint stopMobileRedirectTog

Мы хотим собрать все таблицы из корпуса. Таким образом, у нас есть меньшая площадь для поиска.

wiki_tables = soup.find_all('table', class_='wikitable')
wiki_tables

Поскольку существует множество таблиц, нам нужен способ их фильтрации.

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

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

links = []
for table in wiki_tables:
_table = table.find('a', string=re.compile('Cristiano Ronaldo'))
if not _table:
continue
print(_table)
_parent = _table.parent
print(_parent)
links.append(_parent)
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>

Родитель показывает нам только ячейку. Нам нужно забраться на дерево повыше.

Вот ячейка с инструментами веб-разработчика браузера.

parent_lst = []
for anchor in links:
   _ = anchor.find_parents('tbody')
   print(_)
   parent_lst.append(_)

Используя tbody, мы можем вернуть другие таблицы, которые будут содержать теги привязки из ранее.

Чтобы отфильтровать еще больше, мы можем искать по различным заголовкам этих таблиц:

for i in parent_lst:
   print(i[0].find('tr'))
tr>
<th>Rank*</th>
<th>Page</th>
<th>Views in millions
</th></tr>
<tr>
<th>Rank</th>
<th>Page</th>
<th>Views in millions
</th></tr>
<tr>
<th>Rank</th>
<th>Page</th>
<th>Sport</th>
<th>Views in millions
</th></tr>

Третий выглядит как та таблица, которую мы хотим.

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

Чтобы разбить это:

sports_table = parent_lst[2]
complete_row = []

Здесь мы выбираем 3-й элемент из списка ранее. Поскольку это тот стол, который мы хотели.

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

Мы создаем цикл, который будет перебирать каждую строку в таблице и сохранять их в переменной rows.

for i in sports_table:
  rows = i.find_all('tr')
  print('\n--------row--------\n')
  print(rows)

for row in rows:
   cells = row.find_all('td')
   print('\n-------cells--------\n')
   print(cells)

Создаем вложенный цикл. Это выполняет итерацию по каждой строке, сохраненной из последнего цикла. При итерации ячеек мы сохраняем отдельные ячейки в новой переменной.

if not cells:
  continue

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

rank = cells[0].text.strip('\n')
page_name = cells[1].find('a').text
sport = cells[2].find('a').text
views = cells[3].text.strip('\n')

Здесь мы очищаем различные ячейки в виде простого текста. Очищенные значения сохраняются в переменных под именами своих столбцов.

print('\n-------CLEAN--------\n')
print(rank)
print(page_name)
print(sport)
print(views)
complete_row.append([rank, page_name, sport, views])

Здесь мы добавляем значения в список строк. И распечатайте очищенные значения.

-------cells--------
[<td>13
</td>, <td style="text-align: left;"><a href="/wiki/Conor_McGregor" title="Conor McGregor">Conor McGregor</a>
</td>, <td><a href="/wiki/Mixed_martial_arts" title="Mixed martial arts">Mixed martial arts</a>
</td>, <td>43
</td>]
-------CLEAN--------
13
Conor McGregor
Mixed martial arts
43

Теперь преобразуем его в фрейм данных:

headers = ['Rank', 'Name', 'Sport', 'Views Mil']
df = pd.DataFrame(complete_row, columns=headers)
df

Теперь у нас есть фреймворк pandas, который вы можете использовать для своего проекта ML. Вы можете использовать свою любимую библиотеку, чтобы подогнать модель под данные.

Если вы нашли эту статью интересной, тогда просмотрите мой список рассылки. Где я пишу еще такие вещи