Итак, я пытаюсь создать бота, который идентифицирует списки кредитов NFT по размытию, которые соответствуют определенным критериям, таким как общая стоимость кредита, составляющая 80% или меньше минимальной цены, или APY, превышающая 100%. Я разобрался с основами загрузки Chrome с помощью селена и перехода к нужному разделу веб-сайта для просмотра кредитов на коллекции. Но я изо всех сил пытаюсь извлечь данные из таблицы кредитов. Что мне хотелось бы сделать, так это извлечь таблицу списков кредитов в массив массивов или массив словарей, где каждый массив/словарь содержит данные, представляющие каждое имя, статус, сумму займа, LTV и APY.
Что я работаю до сих пор:
import selenium
from selenium.webdriver.common.by import By
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.keys import Keys
import time
path = "/Users/#########/Desktop/chromedriver-mac-arm64/chromedriver"
# Create an instance of ChromeOptions
options = Options()
options.add_experimental_option("detach", True)
options.add_argument("disable-infobars");
# Specify the path to the ChromeDriver
service = Service(path)
# Initialize the WebDriver with the service and options
driver = webdriver.Chrome(service=service, options=options)
# Open Blur beanz collection and navigating to active loans page
driver.maximize_window
driver.get("https://blur.io/eth/collection/beanzofficial/loans")
time.sleep(3)
loan_button = driver.find_element(By.XPATH, "/html/body/div/div/main/div/div[3]/div/div[2]/div[1]/div[1]/nav/button[2]")
loan_button.click()
Честно говоря, я новичок в селене, поэтому просто играл со своей интуицией и чатом, пытаясь решить эту проблему. Лучшее предположение, которое у меня было до сих пор, — это следующий фрагмент кода, который пытался извлечь APY всех кредитов. Это не сработало, так как я уверен, что это была какая-то ошибочная интуиция.
elements = driver.find_elements(By.CSS_SELECTOR, 'Text-sc-m23s7f-0 hAGCAO')
# Initialize an empty list to store the percentage values
percentages = []
# Iterate through each element and extract its text (which contains the percentage)
for element in elements:
percentage = element.text
percentages.append(percentage)
# Print the extracted percentage values
print(percentages)
time.sleep(10)
# Close the WebDriver
driver.quit()
Мне также кажется, что это немного сложно: нужно извлекать каждый столбец таблицы, а не каждую строку за раз. Не уверен, что есть более простой способ сделать это, если бы он был, было бы здорово. Если нет, тоже ок!
@ryyyn О, спасибо, я этого не заметил. Хотя на самом деле я просто пытаюсь реализовать этот проект, чтобы освоиться с селеном и в конечном итоге создать небольшое приложение для своего резюме. Так что, если у вас есть какие-либо советы о том, как заставить это работать с селеном, мы будем очень признательны! еще раз спасибо, ура.






Чтобы получить данные таблицы, я бы проанализировал элемент <script>, где данные хранятся в формате Json:
import json
import pandas as pd
import requests
from bs4 import BeautifulSoup
url = "https://blur.io/"
soup = BeautifulSoup(requests.get(url).content, "html.parser")
data = json.loads(soup.select_one("#__NEXT_DATA__").text)
table = data["props"]["pageProps"]["sections"]["tableCollections"]
for tab, data in zip(table["tabs"], table["data"]):
df = pd.DataFrame(data)
del df["iconUrl"]
values = df.pop("values").apply(pd.Series)
values.columns = table["headings"][1:]
df = pd.concat([df, values], axis=1)
print(tab)
print(df)
print()
Распечатки:
Trending
collectionUrl title Floor Price 1D Change 7D Change 1D Volume 7D Volume Owners Supply
0 https://blur.io/collection/lilpudgys LilPudgys 0.67 -12.89 -22.77 149.34 855.78 8269 21663
1 https://blur.io/collection/degods-eth DeGods 0.77 -8.62 -32.22 49.83 640.14 2006 5679
2 https://blur.io/collection/clonex CloneX 0.40 -0.12 -4.52 42.39 219.07 9488 19600
3 https://blur.io/collection/mypethooligan My Pet Hooligan 0.34 -4.39 -12.42 9.83 68.65 3528 8888
4 https://blur.io/collection/cryptochasers-robot CryptoChasers Robot 0.88 0.00 0.00 0.88 0.88 472 499
5 https://blur.io/collection/proof-moonbirds Moonbirds 0.38 -10.93 -19.20 17.23 97.76 5797 10000
6 https://blur.io/collection/bored-ape-kennel-club BoredApeKennelClub 0.29 -12.28 -20.81 33.17 162.73 5076 9602
7 https://blur.io/collection/influenceth-asteroids Influence Asteroids 0.02 55.83 -18.33 1.93 2.77 1936 9666
8 https://blur.io/collection/lacma-cactoid-labs-rotf-vol-1 LACMA Remembrance of Things Future Volume #1 0.30 -24.05 -24.53 0.20 1.15 118 500
9 https://blur.io/collection/beanzofficial Beanz 0.17 -19.08 -20.61 30.37 153.57 7677 19950
10 https://blur.io/collection/murakami-flowers-2022-official Murakami.Flowers 0.15 -0.07 5.57 1.29 11.11 5365 10153
11 https://blur.io/collection/habbo-avatars Habbo Avatars 0.12 -0.69 -4.17 1.49 8.76 4410 11599
12 https://blur.io/collection/deadfellaz DeadFellaz 0.07 -0.14 -4.27 0.56 1.98 6413 10000
13 https://blur.io/collection/trainersgen1 Pixelmon Trainers - Generation 1 0.08 -13.26 -17.59 0.25 11.89 1254 7000
14 https://blur.io/collection/str8fire-og-pass STR8FIRE OG PASS 0.05 -14.11 39.15 0.17 3.48 548 1200
Top
collectionUrl title Floor Price 1D Change 7D Change 1D Volume 7D Volume Owners Supply
0 https://blur.io/collection/pudgypenguins PudgyPenguins 7.29 -22.60 -28.50 894.49 2565.28 5182 8888
1 https://blur.io/collection/boredapeyachtclub BoredApeYachtClub 8.89 -12.17 -24.25 680.12 3546.91 5460 9998
2 https://blur.io/collection/milady Milady 4.73 -0.46 15.29 279.38 3113.31 5135 9978
3 https://blur.io/collection/mutant-ape-yacht-club MutantApeYachtClub 1.47 -13.48 -20.11 219.61 2203.20 11658 19495
4 https://blur.io/collection/remilio-babies Redacted Remilio Babies 1.28 -9.81 4.56 209.64 1303.70 4610 9998
5 https://blur.io/collection/lilpudgys LilPudgys 0.67 -12.89 -22.77 149.34 855.78 8269 21663
6 https://blur.io/collection/azuki Azuki 3.20 -10.64 -15.13 128.56 1994.88 4255 10000
7 https://blur.io/collection/degods-eth DeGods 0.77 -8.62 -32.22 49.09 640.54 2005 5679
8 https://blur.io/collection/kanpai-pandas Kanpai Pandas 0.79 -15.17 -16.16 48.26 330.87 3191 7976
9 https://blur.io/collection/clonex CloneX 0.40 -0.12 -4.52 42.39 219.07 9488 19600
10 https://blur.io/collection/pixelmongen1 Pixelmon 0.44 -10.41 -9.65 37.48 191.28 2599 12566
11 https://blur.io/collection/bored-ape-kennel-club BoredApeKennelClub 0.29 -12.28 -20.81 33.17 162.73 5076 9602
12 https://blur.io/collection/persona Persona 0.22 -11.29 -13.96 30.89 200.20 3222 8875
13 https://blur.io/collection/sappy-seals Sappy Seals 0.42 -13.36 -18.76 30.79 135.66 1618 9997
14 https://blur.io/collection/beanzofficial Beanz 0.17 -19.08 -20.61 30.37 153.57 7677 19950
Как мне тогда получить данные о кредите? Это очень полезно, спасибо!
@number2patrician А где находятся данные по кредитам?
Я бы порекомендовал поискать «как найти элементы с помощью Selenium» и немного почитать. Но, возможно, это поможет вам начать...
Ваш XPATH для выбора кнопки «ВСЕ КРЕДИТЫ» — /html/body/div/div/main/div/div[3]/div/div[2]/div[1]/div[1]/nav/button[2] — очевидно, что вы получили его, нажав «Копировать XPATH» в консоли разработчика. Как правило, это не очень хороший подход, потому что если что-то в структуре страницы изменится, ваш код сломается (представьте, что разработчик решает добавить или удалить элемент div в любом месте этой иерархии). Вместо этого попытайтесь найти уникальный способ выбрать элемент, который вряд ли изменится. Выбор по идентификатору (например: driver.find_element(By.ID, "main-menu")) предпочтителен, если это возможно. На этой странице кнопка «ВСЕ КРЕДИТЫ» не имеет идентификатора или уникального имени класса — в этом случае я предпочитаю использовать текст для поиска элемента. Мой рекомендуемый XPATH: //button[.='All Loans']. Этот XPATH означает, что нужно выбрать все элементы <button> в любом месте страницы, строковое содержимое которых равно «Все кредиты». (Обратите внимание, что этот текст, соответствующий регистру, чувствителен к регистру — даже несмотря на то, что текст «ВСЕ КРЕДИТЫ» отображается на странице в верхнем регистре, если вы проверите HTML-код, вы увидите, что фактический текст написан с заглавной буквы).
Чтобы протестировать XPATH в Chrome, откройте средство просмотра HTML (вкладка «Элементы» консоли разработчика) и нажмите CTRL+F, чтобы открыть панель поиска, затем введите свой XPATH (без кавычек). Вы увидите, сколько элементов расположено с помощью XPATH.
Для выбора кредитов вы можете использовать XPATH: //div[@id= 'COLLECTION_MAIN']//div[@role='rowgroup']//div[@role='row']. Сначала он находит <div> с идентификатором «COLLECTION_MAIN» — это центральная область экрана. Затем он находит элемент-потомок div "rowgroup", который содержит займы и, наконец, все сами строки. Вы можете попробовать поиграться с этим XPATH — если вы удалите любой из первых компонентов селектора, это не сработает, поскольку он найдет дополнительные элементы div с ролью «строка».
Затем вы можете перебирать эти строки, чтобы получить любую необходимую информацию.
Собираем это вместе:
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
...
options = Options()
options.add_experimental_option("detach", True)
# disable the message "Chrome being controlled by automated test software"
options.add_experimental_option("excludeSwitches",["enable-automation"])
driver = webdriver.Chrome(service=service, options=options)
# Open Blur beanz collection and navigating to active loans page
driver.maximize_window() # fixed typo
driver.get("https://blur.io/eth/collection/beanzofficial/loans")
# wait until element is clickable then click it
loans_button = WebDriverWait(driver, 20).until(
EC.element_to_be_clickable((By.XPATH, "//button[.='All Loans']")))
loans_button.click()
percentages = []
# wait for table to load
WebDriverWait(driver, 10).until(
EC.presence_of_element_located((By.XPATH, "//div[@id= 'COLLECTION_MAIN']//div[@role='rowgroup']//div[@role='row']")))
for loan_row in driver.find_elements(By.XPATH, "//div[@id= 'COLLECTION_MAIN']//div[@role='rowgroup']//div[@role='row']"):
apy = loan_row.find_element(By.XPATH, "div[5]").text # select the 5th column
percentages.append(apy) # could use float(apy[:-1]) to convert to number
Обновлено: ответ Андрея намного превосходит с точки зрения простоты и скорости - использование Selenium для очистки данных действительно должно быть последним средством.
Для меня это не заполняет массив процентов. Это сработало для вас?
хм, да, я проверил это, и у меня это работает... заранее извините за этот вопрос, но вы включили строку для печати percentages? (это не в моем коде). В противном случае выполните отладку вручную. Откройте REPL, вставьте код построчно и посмотрите, какие значения вы получите. Это очень полезно, потому что вы можете попробовать разные селекторы/разные функции гораздо быстрее, чем каждый раз перезапускать скрипт. (И это применимо к любому проекту Python, особенно при работе с чем-то незнакомым, например с исходным веб-кодом, где вам наверняка придется попробовать разные подходы)
да, я включил это, ха-ха. Вероятно, я где-то допустил какую-то другую простую ошибку, я посмотрю и попробую ваше предложение. Огромное спасибо за ваши ответы, это очень помогло!
Я добавил строки, содержащие путь к драйверу Chrome и service = Service(path) к «...» в вашем коде и печать в конце, но это просто печать пустого массива! не знаю, что мне здесь не хватает ;{
Если он не добавляет элементы в массив и не поднимает Exception, это означает, что driver.find_elements(By.XPATH, "//div[@id='COLLECTION_MAIN']//div[@role='rowgroup']//div[@role='row']") возвращает пустой массив... вы пробовали запускать его построчно, как я предлагал? Если это работает для вас, но запуск скрипта — нет, возможно, сайт загружается у вас медленнее, и поэтому после нажатия кнопки «ВСЕ КРЕДИТЫ» требуется небольшая задержка; можешь попробовать добавить time.sleep(1)
Да, это было именно то, спасибо!
Похоже, Blur скоро выпустит API - обязательно отправьте форму для регистрации доступа, поскольку использование API всегда НАМНОГО быстрее/проще, чем использование Selenium. Обновлено: я нашел эту форму, щелкнув ссылку «API» внизу домашней страницы Blur.io.