#python #jquery #selenium #web-scraping #download
#python #jquery #selenium #очистка веб-страниц #Скачать
Вопрос:
Я создаю загруженный файл для автоматической загрузки PDF-файлов с веб-сайта, связанного с компанией моего работодателя.
Похоже, что PDF-файлы содержатся в JQueryFileTree. Есть ли способ загрузить одну из папок ниже и сохранить ее на диск вместе с содержимым PDF-файла?
До сих пор я использую Python и selenium для автоматизации входа в систему и т.д.
Спасибо
Мой код пока:
from selenium import webdriver
from time import sleep
import requests
from bs4 import BeautifulSoup as bs
import secrets
class manual_grabber():
""" A class creating a manual downloader for the Roger Technology website """
def __init__(self):
""" Initialize attributes of manual grabber """
self.driver = webdriver.Chrome('\Users\Joel\Desktop\Python\manual_grabber\chromedriver.exe')
def login(self):
""" Function controlling the login logic """
self.driver.get('urltosite')
sleep(1)
# Locate elements and enter login details
user_in = self.driver.find_element_by_xpath('/html/body/div[2]/form/input[6]')
user_in.send_keys(secrets.username)
pass_in = self.driver.find_element_by_xpath('/html/body/div[2]/form/input[7]')
pass_in.send_keys(secrets.password)
enter_button = self.driver.find_element_by_xpath('/html/body/div[2]/form/div/input')
enter_button.click()
# Click Self Service Area button
self_service_button = self.driver.find_element_by_xpath('//*[@id="bs-example-navbar-collapse-1"]/ul/li[1]/a')
self_service_button.click()
grab = manual_grabber()
grab.login()
При нажатии на одну из этих папок открывается содержимое PDF-файла в окне справа от дерева.
Комментарии:
1. Привет, не могли бы вы, пожалуйста, поделиться своим кодом на данный момент, структурой DOM и тем, как бы вы вручную загрузили папку с такого дисплея?
2. @RichEdwards Привет, я отредактировал свой вопрос, показывающий структуру файла и т.д. Вы не можете загрузить папку непосредственно вручную. Вы можете загрузить каждый отдельный файл, нажав на кнопку загрузить с правой стороны. Надеюсь, это поможет.
3. Selenium сделает то, что вы можете сделать — как бы вы загрузили файлы? — я полагаю, щелкните дерево слева, затем нажмите кнопку загрузки справа? — … для selenium определите элемент дерева (по возможности по тексту), используйте find_elements (множественное число) для всех
a
, которые соответствуют вашим критериям, и выполняйте цикл, чтобы загрузить все — или используйте библиотеку, подобную libcurl, для управления загрузками из href, поскольку загрузка из sleneium «неконтролируема» (т. Е. нет ida прогресса) — если вы можете поделиться DOM из devtools для каждого из этапов, я могу помочь вам с идентификаторами, в противном случае псевдо- это насколько я могу зайти4. @RichEdwards Спасибо за это. Я ценю вашу помощь!
5. @RichEdwards После попытки использовать функцию .click () в левом дереве, он сообщает мне, что не может найти элемент. Это потому, что он содержится внутри JQueryFileTree или это не имеет значения?
Ответ №1:
На основе DOM и скриншотов вы сможете выбирать из своего дерева jquery.
вы можете использовать этот xpath для выбора из дерева слева:
//a[.//nobr[text()='Products catalogue and brouches']]
Для этого xpath:
//a
является относительнымa
(в любом месте страницы)- запуск
[
означает, что мы идентифицируем его с… .
дочерний файл из этого местоположения (т. Е. подa
)//nobr
любой тег nobr- где
text()
= ‘Каталог продукции и брошюры’ (чувствителен к регистру)
Короче говоря, это любой файл, a
у которого есть дочерний элемент nobr
, содержащий нужный нам текст.
Я поместил это на простую страницу, и оно уникально соответствует результату:
Существует намного больше идентификаторов xpath и подходов — это отличный учебный ресурс.
Надеюсь, с помощью этого xpath вы можете просто ввести текст, который хотите щелкнуть, и он сделает это за вас.
Если ваши идентификаторы не найдены — пожалуйста, дайте мне знать, и я посмотрю еще раз.
Несколько дополнительных мыслей для q1:
В зависимости от вашего приложения и того, как работает дерево, вам может понадобиться стратегия ожидания.
Существует 2 основных подхода, явный и неявный. Для простоты (поскольку этот ответ уже достаточно длинный), попробуйте сначала неявное ожидание:
driver.implicitly_wait(10)
установите это ЗНАЧЕНИЕ ОДИН РАЗ в вашем __init__
и selenium будет ждать до 10 секунд, прежде чем жаловаться на несуществующие объекты. (если это не сработает, дайте мне знать!)
Вам также может потребоваться прокрутить ваше дерево, чтобы отобразить элемент. В этом случае попробуйте это — просто идентифицируйте свой элемент с помощью xpath выше и передайте его сюда:
def ScrollIntoView(element):
actions = ActionChains(driver)
actions.move_to_element(element).perform()
Следующая часть вашего вопроса касается загрузки файлов. Щелкаем по ссылкам справа.
Вам нужно будет предоставить больше общего доступа к DOM — если вы можете предоставить общий доступ к 2 или 3 из тех a
файлов или изображений, которые инициируют загрузку, я смогу предоставить индивидуальный ответ.
В общих чертах, если вы хотите получить «все» ссылки для загрузки, вам нужно сделать что-то вроде:
#get all the elements - needs a condition that identifies just these anchors
allLinks = driver.find_elements_by_xpath(some condition)
#loop through all links and action the click
for link in allLinks:
link.click()
time.sleep(3) # don't download too many at once - depending on their size let them complete
Загрузка файла в selenium возможна, но вы не можете получить размер загрузки, прогресс или скорость. По сути, вы закрываете на это глаза, как только оно запускается.
Есть альтернативы, но они увеличивают сложность.
Держите меня в курсе дополнительных материалов по DOM, если вам нужна дополнительная помощь. Рад продолжить поиск и предоставить дополнительную поддержку.
Обновление из комментариев ниже. Для управления iframes вам необходимо определить его и переключиться на него, чтобы выполнять свои действия. Я не могу протестировать xpath — так что попробуйте и обновите его по мере необходимости.
frame = driver.find_element_by_xpath('//iframe[contains(@src,"ManageFiles")]')
driver._switch_to.frame(frame)
#do the actions on the frame
#when ready...
driver._switch_to.default_content()
В конце обязательно переключитесь обратно на содержимое по умолчанию или на следующий iframe, с которым необходимо взаимодействовать.
Переключитесь, найдите и щелкните с помощью waits:
WebDriverWait(driver, 15).until(EC.frame_to_be_available_and_switch_to_it((By.XPATH,'//iframe[contains(@src,"ManageFiles")]')))
#Watch spelling and case on this line
myListObject = WebDriverWait(driver, 15).until(EC.element_to_be_clickable((By.XPATH,"//a[.//nobr[text()='Products catalogue and brochures']]")))
myListObject.click()
Комментарии:
1. Радость от того, что я не могу протестировать код, прежде чем попробовать его 🙂 — сначала проверьте, что это находит элемент:
element = self.driver.find_element_by_xpath("//a[.//nobr[text()='Products catalogue and brochures']]")
— следите за любыми орфографическими ошибками в тексте () — я не смог скопировать и вставить, и вместо него выше я напечатал «brouches» (не брошюры)2. если это позволяет найти элемент, но вы не можете этого сделать
element.click()
— вы можете попробовать это как план бdriver.execute_script("arguments[0].click();",element)
… Если бы у меня был доступ к вашему сайту, я бы попробовал все это для вас и протестировал все это3. существуют ли они
frames
илиiframes
присутствуют? (они нуждаются в специальной обработке) — вы, вероятно, уже сделали это, но проверьте правописание или попробуйте другой элемент дерева, который вы можете увидеть — и, если вы еще этого не сделали. запустите xpath в devtools, чтобы посмотреть, найдет ли это 🙂4. Добавлено обновление с некоторым примером кода в конце обработки фреймов с помощью selenium
5. @j4yman Это сложно из-за изображения — обычно это процесс проб и ошибок для точной настройки xpaths и ожиданий. Я добавил еще один новый раздел внизу, который включает в себя синхронизацию поиска и щелчка… Если это не сработает, мне нужно узнать об ошибке, пожалуйста, ответьте… И, пожалуйста, следите за орфографией и регистром в элементах! Вы сможете щелкнуть, только если элемент виден, поэтому измените его на элемент более высокого уровня, если дерево нуждается в расширении