Автор оригинала: Otávio Simões Silveira.
Selenium – это инструмент, предназначенный для того, чтобы помочь вам запустить автоматические тесты в веб-приложениях. Он доступен на нескольких различных языках программирования.
Хотя это не его главная цель, Selenium также используется в Python для веб-соскабливания, потому что он может получить доступ к JavaScript-представленному контенту (который обычные инструменты соскабливания, как BeautificSoup, не могут сделать).
Selenium также полезен, когда вам нужно как-то взаимодействовать с страницей, прежде чем собирать данные, такие как нажатие кнопок или заполнения полей. Это использование случая, которое будет покрыто в этой статье.
В качестве примера мы будем соскрести Investing.com для извлечения исторических данных курсов долларовых курсов против одной или нескольких валют.
Если вы ищете в Интернете, вы можете найти пакеты API и Python, которые делают его намного проще сбора финансовых данных (вместо того, чтобы соскоб его вручную). Тем не менее, идея здесь состоит в том, чтобы исследовать, как Selenium может помочь вам с общими добычей данных.
Сайт, который мы собираемся соскребать
Во-первых, нам нужно понять сайт. Этот сайт Содержит исторические данные об обмене курс доллара по отношению к евро.
На этой странице вы можете увидеть таблицу с данными и возможность установить нужный диапазон дата. Это то, что мы собираемся использовать.
Чтобы увидеть данные для других валют по отношению к доллару, просто замените « EUR » с другим кодом валют в URL.
Кроме того, это предполагает, что вы хотите только обменный курс валюты по отношению к доллару. Если это не так, просто замените «USD» в URL.
Код скребка
Мы начнем с импорта, и нам больше не нужно. Давайте импортируем полезные предметы из селена: Спать
Функция, чтобы вставить некоторые паузы в код и панды для манипулирования датой при необходимости.
from selenium import webdriver from selenium.webdriver.chrome.options import Options from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.by import By from time import sleep import pandas as pd
Далее мы напишем функцию, чтобы соскрести данные. Функция получит:
- Список кодов валют
- Дата начала
- Дата окончания
- Булевая информирование, если мы хотим экспортировать данные как .csv файл. Я буду использовать false как по умолчанию.
Кроме того, в качестве идеи здесь состоит в том, чтобы построить скребок, способный сбрать данные о нескольких валютах, мы также инициализируем пустой список для хранения данных из каждой валюты.
def get_currencies(currencies, start, end, export_csv=False): frames = []
Поскольку функция теперь имеет список валют, вы, вероятно, представляете, что мы будем повторять этот список и получать валюту данных по валюте. Это именно план.
Таким образом, для каждой валюты в списке валют мы создадим URL, создать объект драйвера и использовать его, чтобы получить страницу. Тогда мы максимизируем окно, но это только видно, если вы сохраните Опция. Бокан ... как ложь. В противном случае Selenium сделает всю работу, не показывая вам ничего.
for currency in currencies: my_url = f'https://br.investing.com/currencies/usd-{currency.lower()}-historical-data' option = Options() option.headless = False driver = webdriver.Chrome(options=option) driver.get(my_url) driver.maximize_window()
Мы уже смотрим на исторические данные на данный момент, и мы могли бы просто получить таблицу с данными. Однако по умолчанию мы видим только данные о последних 20 дней. Мы хотим получить эти данные за любой период времени.
Для этого мы будем использовать некоторые интересные функции Selenium, чтобы взаимодействовать с веб-сайтом. Это когда селеновый сияет!
Что мы будем делать здесь, нажимайте на даты и заполните дату начала и поля окончания даты с датами, которые мы хотим, и применить удар.
Для этого мы будем использовать WebDriverwait
, Ожидаемые ободрения
и По
Чтобы убедиться, что веб-драйвер будет дождаться элементов, которые мы хотим взаимодействовать, чтобы быть кликабельными.
Это важно, потому что если дайвер пытается взаимодействовать с чем-то, прежде чем он станет кликабельным, будет поднят исключение.
Время ожидания будет двадцать секунд, но решать вам, чтобы установить его, как вы находите подходящие. Во-первых, давайте выберем кнопку Дата на XPath, а затем нажмите на нее.
date_button = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[5]/section/div[8]/div[3]/div/div[2]/span"))) date_button.click()
Теперь нам нужно заполнить поле даты начала. Давайте сначала выберете его, а затем используйте ясно
Чтобы удалить дату по умолчанию и send_keys
Чтобы заполнить его датой, которую мы хотим.
start_bar = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[7]/div[1]/input[1]"))) start_bar.clear() start_bar.send_keys(start)
И теперь мы повторяем процесс поля окончания даты.
end_bar = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[7]/div[1]/input[2]"))) end_bar.clear() end_bar.send_keys(end)
С этим сделано, мы выберем кнопку Применить и нажмите на нее. Тогда мы используем Спать
Чтобы приостановить код в течение нескольких секунд и убедиться, что новая страница полностью загружена.
apply_button = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[7]/div[5]/a"))) apply_button.click() sleep(5)
Если у вас было Опция. Бокан ... Как False, вы увидите весь этот процесс, происходящий перед вами, как если бы кто-то был на самом деле нажал на странице. Когда Selenium нажимает на применение, вы увидите таблицу, перезагружающую, чтобы показать данные для указанного вами периода времени.
Теперь мы используем Pandas.read_html
Функция, чтобы выбрать все таблицы на странице. Эта функция получит исходный код страницы. Наконец, мы можем бросить водитель.
dataframes = pd.read_html(driver.page_source) driver.quit() print(f'{currency} scraped.')
Как обрабатывать исключения в селении
Процесс сбора данных сделан. Но нам нужно учитывать, что Selenium иногда может быть немного нестабильным и в конечном итоге может не загружать страницу в какой-то момент во время всех действий, которые мы выполняемым здесь.
Чтобы предотвратить это, у нас будет весь код внутри попробуйте
пункт, который будет внутри петли Infinity. Как только Selenium удается собирать данные, как я описал выше, цикл будет нарушен. Но каждый раз он находит проблему, ожидать
пункт будет активирован.
В этом сценарии код будет:
- Выйдите водителя – всегда важно сделать это, поэтому мы не заканчиваем десятки памяти потребляющих веб-драйверов
- Распечатайте сообщение, указывающее на ошибку
- Спать на тридцать секунд
- Перейти к началу петли еще раз
Этот процесс будет повторяться до тех пор, пока данные для каждой валюты не будут правильно. И это код для всего этого:
for currency in currencies: while True: try: # Opening the connection and grabbing the page my_url = f'https://br.investing.com/currencies/usd-{currency.lower()}-historical-data' option = Options() option.headless = False driver = webdriver.Chrome(options=option) driver.get(my_url) driver.maximize_window() # Clicking on the date button date_button = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[5]/section/div[8]/div[3]/div/div[2]/span"))) date_button.click() # Sending the start date start_bar = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[7]/div[1]/input[1]"))) start_bar.clear() start_bar.send_keys(start) # Sending the end date end_bar = WebDriverWait(driver, 20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[7]/div[1]/input[2]"))) end_bar.clear() end_bar.send_keys(end) # Clicking on the apply button apply_button = WebDriverWait(driver,20).until( EC.element_to_be_clickable((By.XPATH, "/html/body/div[7]/div[5]/a"))) apply_button.click() sleep(5) # Getting the tables on the page and quiting dataframes = pd.read_html(driver.page_source) driver.quit() print(f'{currency} scraped.') break except: driver.quit() print(f'Failed to scrape {currency}. Trying again in 30 seconds.') sleep(30) continue
Один последний шаг, хотя. Если вы вспомните, что мы до сих пор – это список, содержащий все таблицы на странице, хранящуюся в виде DataFrames. Нам нужно выбрать одну таблицу, которая содержит исторические данные, которые мы хотим.
Для каждого DataFrame в этом списке DataFrames мы проверим, соответствует ли название его столбцов, соответствует тому, что мы ожидаем. Если они сделают, то это наш кадр, и мы разбиваем петлю. И теперь мы наконец готовы добавить этот файл DataFrame в список, который был инициализирован в начале.
for dataframe in dataframes: if dataframe.columns.tolist() == ['Date', 'Price', 'Open', 'High', 'Low', 'Change%']: df = dataframe break frames.append(df)
И да, если export_csv
Параметр был установлен на true, нам нужно будет экспортировать .csv файл. Но это далеко не проблема, как Dataframe.to_csv
Метод может легко получить это.
И тогда мы можем просто обернуть эту функцию, вернув список данных данных. Этот последний шаг сделан после окончания списка циклов через список валют, конечно.
if export_csv: df.to_csv('currency.csv', index=False) print(f'{currency}.csv exported.') # Outside of the loop return frames
Вот и все! Вот полный код для этих двух последних шагов в сочетании:
# Selecting the correct table for dataframe in dataframes: if dataframe.columns.tolist() == ['Date', 'Price', 'Open', 'High', 'Low', 'Change%']: df = dataframe break frames.append(df) # Exporting the .csv file if export_csv: df.to_csv('currency.csv', index=False) print(f'{currency}.csv exported.') return frames
Следующие шаги и упаковка
Пока что этот код получает исторические данные обменного курса списка валют по отношению к доллару и возвращает список данных данных и несколько .csv файлы.
Но есть всегда комната для улучшения. Благодаря еще нескольким строкам кода не трудно сделать функцию возврата и экспортировать один DataFrame, содержащий данные для каждой валюты в списке.
Еще одно предложение – написать Обновить
Функция, использующая те же функции селена, которые получают существующее dataframe и обновлять исторические данные на настоящую дату.
Кроме того, то же самое, такую же логику, используемую для царапания валют, можно использовать для скрепления запасов, индексов, товаров, фьючерсов и многого другого. Есть так много страниц, которые вы можете соскребать.
Однако, если это цель, то важно вставить больше пауз в код, чтобы избежать перегрузки сервера. Вы также должны воспользоваться провайдером прокси, например Infatica , чтобы убедиться, что ваш код будет продолжать работать до тех пор, пока есть страницы, которые остаются страницы, и что вы и ваше соединение защищены.
Наконец, Selenium может быть полезен в нескольких других ситуациях, таких как вход в веб-сайты, заполнение форм, выбирая элементы в раскрывающемся списке и многое другое. Конечно, это не единственное решение для таких проблем, но это определенно может быть полезно в зависимости от случая использования.
Я надеюсь, что вам понравилось эту статью и что она помогла вам. Если у вас есть вопрос или предложение, не стесняйтесь быть на связи Отказ