3 способа сбора данных для DS-проекта.

3 способа сбора данных для DS-проекта.

https://t.me/Golang_google


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

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

Так случилось со мной, когда я искал данные о футбольных матчах, проведенных на Чемпионатах мира с 1930 по 2022 год. Некоторые данные были извлечены, но не все. С помощью этого руководства мы извлечем остальные данные с нуля с помощью Selenium, чтобы в дальнейшем использовать их в проекте.

Шаг 1. Установка Selenium

Чтобы установить Selenium, откроем терминал и выполним следующую команду:

pip install selenium

Теперь загрузите версию Chromedriver, подходящую для вашего компьютера.

  • Проверьте версию вашего Google Chrome (нажмите на три точки, кликните на “help”, а затем выберите “about Google Chrome”).
  • Скачайте нужную версию Chromedriver здесь (после обновления Chrome скачайте файл снова).
  • Распакуйте скачанный файл и скопируйте путь к файлу Chromedriver.

Шаг 2. Веб-скрейпинг одной страницы

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

from selenium import webdriver
from selenium.webdriver.chrome.service import Service
import time
import pandas as pd
  • Selenium — для сбора данных.
  • Time — для добавления времени ожидания при автоматизации сайта.
  • Pandas — для организации извлеченных данных в датафреймы.

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

  • path  — местонахождения файла Chromedriver.
  • web  — сайт, который вы собираетесь скрейпить (мы будем скрейпить эту страницу).
  • driver  — объект, который поможет проводить скрейпинг сайта.
path = # Здесь прописываем путь
service = Service(executable_path=path)
driver = webdriver.Chrome(service=service)
web = 'https://en.wikipedia.org/wiki/1982_FIFA_World_Cup'

Теперь, чтобы открыть Chromedriver и перейти на целевой сайт, выполним следующую строку кода:

driver.get(web)

Появится новое окно с сообщением “Chrome is controlled by automated test software” (“Chrome управляется автоматизированным тестовым программным обеспечением”).

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

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

После выделения строки получим HTML-элемент, который стоит за ней.

<tr style="font-size:90%">

Теперь, чтобы найти этот элемент с помощью Selenium, нужно создать его XPath. Вот синтаксис XPath:

Если заменить каждый элемент, получим следующее:

//tr[@style="font-size:90%"]

Создав XPath, мы можем использовать .find_elements для поиска такого элемента с помощью Selenium.

matches = driver.find_elements(by='xpath', value='//tr[@style="font-size:90%"]')

Переменная matches  — это список, содержащий 48 строк/матчей, перечисленных на сайте. Пройдясь по этому списку, получим все элементы td, поскольку они являются дочерними узлами элемента tr, XPath которого мы создали ранее.

Элементы td содержат данные о команде хозяев поля, счете и команде-гостье. Мы можем получить эти данные с помощью следующих XPath.

  • /td[1]  — команда хозяев поля.
  • /td[2]  — счет.
  • /td[3]  — команда-гостья.

Пройдемся по matches и сохраним данные в пустых списках, которые назовем home (хозяева), score (счет) и away (гости).

home = []
score = []
away = []

for match in matches:
    home.append(match.find_element(by='xpath', value='./td[1]').text)
    score.append(match.find_element(by='xpath', value='./td[2]').text)
    away.append(match.find_element(by='xpath', value='./td[3]').text)

Обратите внимание на добавление . перед исходным /td XPath. Это связано с тем, что теперь используется не driver.find_element, а match.find_element (символ . указывает на то, что поиск начинается с узла match).

Кроме того, добавляется атрибут text, чтобы получить текст, содержащийся в узле (например, Англия, 3–1, Франция).

Наконец, создаем датафрейм из списков homescore и away. Добавляем новый столбец year (год), время ожидания — 2 секунды (это необязательно) и выходим из driver’а.

dict_football = {'home': home, 'score': score, 'away': away} 
df_football = pd.DataFrame(dict_football) 
df_football['year'] = 1982
time.sleep(2)
driver.quit()

Для экспорта датафрейма используем .to_csv.

df_football.to_csv("fifa_worldcup_missing_data.csv", index=False)

Экспортированные данные должны выглядеть так, как показано на изображении ниже, и содержать 48 строк.

Код, написанный до этих пор, можно найти на GitHub. Теперь, немного подправив код, проведем скрейпинг уже не одной, а нескольких страниц.

Шаг 3. Создание функции для скрейпинга нескольких страниц

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

Вот функция, которая позволяет это сделать:

def get_misssing_data(year):
    web = f'https://en.wikipedia.org/wiki/{year}_FIFA_World_Cup'

    driver.get(web)
    matches = driver.find_elements(by='xpath', value='//tr[@style="font-size:90%"]')

    home = []
    score = []
    away = []

    for match in matches:
        home.append(match.find_element(by='xpath', value='./td[1]').text)
        score.append(match.find_element(by='xpath', value='./td[2]').text)
        away.append(match.find_element(by='xpath', value='./td[3]').text)

    dict_football = {'home': home, 'score': score, 'away': away}
    df_football = pd.DataFrame(dict_football)
    df_football['year'] = year
    time.sleep(2)
    return df_football

Обратите внимание, что данная функция использует year в качестве входных данных. Переменная year помещена в ссылку web и столбец df_football[‘year’]. Остальное остается неизменным.

Запустив get_misssing_data(1982), получим тот же результат, что и в шаге 2.

Чтобы извлечь данные с нескольких страниц, создадим список years, содержащий все годы, в которые проводился Чемпионат мира.

years = [1930, 1934, 1938, 1950, 1954, 1958, 1962, 1966, 1970, 1974,
         1978, 1982, 1986, 1990, 1994, 1998, 2002, 2006, 2010, 2014,
         2018]

Теперь с помощью генератора списков проскрейпим страницу, соответствующую каждому году, и сохраним данные в списке с именем fifa. Соберем все списки вместе с помощью .concat и, наконец, экспортируем эти данные в CSV.

fifa = [get_misssing_data(year) for year in years]
driver.quit()
df_fifa = pd.concat(fifa, ignore_index=True)
df_fifa.to_csv("fifa_worldcup_missing_data.csv", index=False)

Теперь в CSV-файле должны быть сотни строк, содержащих все извлеченные данные.


Поздравляем! Вы научились создавать датасеты с помощью Selenium.



Report Page