Я пытаюсь автоматизировать загрузку CSV-файла с URL-адреса Blob на динамическом веб-сайте, используя Selenium с Python. Загрузка CSV запускается нажатием кнопки, но при нажатии кнопки создается URL-адрес большого двоичного объекта, к которому невозможно напрямую получить доступ через традиционные HTTP-запросы. У меня возникли проблемы с захватом и загрузкой файла с этого URL-адреса Blob.
Вот пример URL: https://snapshot.org/#/aave.eth/proposal/0x70dfd865b78c4c391e2b0729b907d152e6e8a0da683416d617d8f84782036349
Вот как выглядит ссылка, когда я проверяю историю загрузок:
капля:https://snapshot.org/4b2f45e9-8ca3-4105-b142-e1877e420c84
Я тоже проверил этот пост Python: как скачать видео с URL-адресом blob? в котором говорилось, что я не смог его загрузить и думаю, что это не имеет смысла, поскольку, когда я открываю веб-страницу вручную, я могу нажать кнопку загрузки и получить файл.
Это код, который я пробовал раньше
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
import time
# Setup ChromeDriver
driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()))
# URL of the proposal page
url = 'https://snapshot.org/#/aave.eth/proposal/0x70dfd865b78c4c391e2b0729b907d152e6e8a0da683416d617d8f84782036349'
# Navigate to the page
driver.get(url)
try:
# Wait up to 20 seconds until the expected button is found using its attributes
wait = WebDriverWait(driver, 20)
download_button = wait.until(EC.element_to_be_clickable((By.XPATH, "//button[contains(.,'svg')]")))
download_button.click()
print("Download initiated.")
except Exception as e:
print(f"Error: {e}")
# Wait for the download to complete
time.sleep(5)
# Close the browser
driver.quit()
Когда я проверяю кнопку «Загрузить CSV», вот что я получил
<svg viewBox = "0 0 24 24" width = "1.2em" height = "1.2em"><path fill = "none" stroke = "currentColor" stroke-linecap = "round" stroke-linejoin = "round" stroke-width = "2" d = "M4 16v1a3 3 0 0 0 3 3h10a3 3 0 0 0 3-3v-1m-4-4l-4 4m0 0l-4-4m4 4V4"></path></svg>
Я не знаю, что вы пытались сделать (потому что вы не показали свой код), но у меня это работает driver.find_elements(By.XPATH, '//button')[10].click()
, но, возможно, потребуется лучший метод, чтобы найти правильную кнопку.
вы не можете получить к нему доступ с помощью традиционного HTTP-запроса, поскольку для отправки файла он запускает некоторый код JavaScript, а традиционный HTTP-запрос не может запускать JavaScript. Вот и все.
@furas, спасибо, я обновил вопрос кодом, который пробовал раньше. Забыл раньше прикрепить. извини
похоже, вы получили изображение SVG, которое было внутри <button>
. На странице много кнопок (около 20), и, возможно, вы ошиблись какой-то. Это может быть самая сложная часть этой программы - найти правильную кнопку :)
Я не знаю, что вы пытались сделать (потому что вы не показали свой код), но у меня это работает.
driver.find_elements(By.XPATH, '//button')[10].click()
но для поиска правильной кнопки может потребоваться лучший метод (вместо [10]
).
Тем временем я нашел этот xpath: "//div[h4//span[contains(text(),'Votes')]]//button"
Полный рабочий код
from selenium import webdriver
from selenium.webdriver.common.by import By
#import undetected_chromedriver as uc
import time
# ---
import selenium
print('Selenium:', selenium.__version__) # Selenium: 4.19.0
# ---
url = 'https://snapshot.org/#/aave.eth/proposal/0x70dfd865b78c4c391e2b0729b907d152e6e8a0da683416d617d8f84782036349'
#driver = webdriver.Chrome() # the newest Selenium will automatically download driver - so it doesn't need `service=`
driver = webdriver.Firefox() # the newest Selenium will automatically download driver - so it doesn't need `service=`
#driver = uc.Chrome()
driver.get(url)
# ---
time.sleep(3)
#all_buttons = driver.find_elements(By.XPATH, '//button')
#all_buttons[10].click()
driver.find_element(By.XPATH, "//div[h4//span[contains(text(),'Votes')]]//button").click()
input('Press ENTER to exit')
driver.close()
Привет Фурас! Спасибо, всё работает. Однако считаете ли вы, что использование такого индекса кнопок является устойчивым решением? Что делать, если есть страница с большим количеством кнопок, на которой будет меняться индекс кнопки? Я пытался осмотреть кнопку, чтобы получить от нее какой-нибудь ключ, но не смог его найти.
индекс может стать проблемой, если страница будет иметь другую структуру - но найти лучший метод - самая сложная часть в этой задаче :) Я не нашел лучшего, но трачу на это всего несколько секунд. возможно, вам стоит найти какой-то другой элемент - там есть <h4>
с текстом Votes
- так что возможно //div[h4[contains(text(), "Votes")]]//button
на данный момент у меня работает "//div[h4]//button"
но я стараюсь использовать contains(text(), "Votes")
наконец, это работает для меня "//div[h4//span[contains(text(),'Votes')]]//button"
. Я добавляю это, чтобы ответить.
что ты пробовал? где твой код? Не ждите, что мы напишем весь код с нуля, чтобы протестировать его.