jupyterhub 페이지에서 python-selenium으로 기존 HTML 요소를 찾는 방법은 무엇입니까?
HTML 페이지에 다음 구문이 있고 li
요소 (python-selenium 사용) 를 선택하고 싶습니다 .
<li class="p-Menu-item p-mod-disabled" data-type="command" data-command="notebook:run-all-below">
<div class="p-Menu-itemIcon"></div>
<div class="p-Menu-itemLabel" style="">Run Selected Cell and All Below</div>
<div class="p-Menu-itemShortcut" style=""></div>
<div class="p-Menu-itemSubmenuIcon"></div>
</li>
다음 xpath를 사용하고 있습니다.
//li[@data-command='notebook:run-all-below']
그러나 요소가 발견되지 않는 것 같습니다.
완전하고 최소한의 작동 예제 코드 :
import time
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
driver = webdriver.Firefox()
driver.get("https://mybinder.org/v2/gh/jupyterlab/jupyterlab-demo/master?urlpath=lab/tree/demo")
# Wait for the page to be loaded
xpath = "//button[@title='Save the notebook contents and create checkpoint']"
element = WebDriverWait(driver, 600).until(
EC.presence_of_element_located((By.XPATH, xpath))
)
time.sleep(10)
print("Page loaded")
# Find and click on menu "Run"
xpath_run = "//div[text()='Run']"
element = WebDriverWait(driver, 60).until(
EC.element_to_be_clickable((By.XPATH, xpath_run))
)
element.click()
print("Clicked on 'Run'")
# Find and click on menu entry "Run Selected Cell and All Below"
xpath_runall = "//li[@data-command='notebook:run-all-below']"
element = WebDriverWait(driver, 600).until(
EC.element_to_be_clickable((By.XPATH, xpath_runall))
)
print("Found element 'Run Selected Cell and All Below'")
element.click()
print("Clicked on 'Run Selected Cell and All Below'")
driver.close()
환경:
- MacOS Mojave (10.14.6)
- 파이썬 3.8.6
- 셀레늄 3.8.0
- 게코 드라이버 0.26.0
추가
나는 파이어 폭스 "Selenium IDE"애드온을 사용하여 단계를 기록하려고 노력하고있다. 이것은 파이썬에 다음 단계를 제공한다.
sdriver.get("https://hub.gke2.mybinder.org/user/jupyterlab-jupyterlab-demo-y0bp97e4/lab/tree/demo")
driver.set_window_size(1650, 916)
driver.execute_script("window.scrollTo(0,0)")
driver.find_element(By.CSS_SELECTOR, ".lm-mod-active > .lm-MenuBar-itemLabel").click()
물론 작동하지 않습니다. 해당 코드 라인으로 오류가 발생합니다.
selenium.common.exceptions.NoSuchElementException: Message: Unable to locate element: .lm-mod-active > .lm-MenuBar-itemLabel
답변
당신은 충분히 가까웠습니다. 사실 전체 프로그램에는 다음과 같은 단 하나의 문제 만있었습니다.
- 는
xpath_runall = "//li[@data-command='notebook:run-all-below']"
같은 텍스트로 보이는 요소를 식별하지 않는 다음 실행 선택한 셀과 모든 첫 번째 일치하는 요소가 그대로 고유 숨겨진 요소입니다.
추가 고려 사항
더 많은 최적화 :
로 식별 된 요소
xpath = "//button[@title='Save the notebook contents and create checkpoint']"
는 클릭 가능한 요소입니다. 그래서 대신에 EC 로presence_of_element_located()
사용할 수element_to_be_clickable()
요소가 EC 를 통해 반환되면 동일한 줄에서를
element_to_be_clickable()
호출 할 수 있습니다click()
.XPath는 같은 텍스트 요소를 식별하기 위해 실행이 셀을 선택하여 모든 다음 과 같다 :
//li[@data-command='notebook:run-all-below']//div[@class='lm-Menu-itemLabel p-Menu-itemLabel' and text()='Run Selected Cell and All Below']
는 AS 응용 프로그램 을 통해 구축 자바 스크립트 당신은 사용할 필요가 ActionChains을 .
해결책
최적화 된 솔루션은 다음과 같습니다.
코드 블록 :
from selenium import webdriver from selenium.webdriver.support.ui import WebDriverWait from selenium.webdriver.common.by import By from selenium.webdriver.support import expected_conditions as EC from selenium.webdriver.common.action_chains import ActionChains driver = webdriver.Firefox(executable_path=r'C:\WebDrivers\geckodriver.exe') driver.get("https://mybinder.org/v2/gh/jupyterlab/jupyterlab-demo/master?urlpath=lab/tree/demo") WebDriverWait(driver, 60).until(EC.element_to_be_clickable((By.XPATH, "//button[@title='Save the notebook contents and create checkpoint']"))) print("Page loaded") WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//div[text()='Run']"))).click() print("Clicked on Run") element = WebDriverWait(driver, 20).until(EC.element_to_be_clickable((By.XPATH, "//li[@data-command='notebook:run-all-below']//div[@class='lm-Menu-itemLabel p-Menu-itemLabel' and text()='Run Selected Cell and All Below']"))) ActionChains(driver).move_to_element(element).click(element).perform() print("Clicked on Run Selected Cell and All Below")
콘솔 출력 :
Page loaded Clicked on Run Clicked on Run Selected Cell and All Below
이것은 나를 위해 일했습니다. 전체 xpath를 사용하여 최상위 메뉴 항목을 찾은 다음 클릭합니다. 팝업 메뉴가 나타날 때까지 잠시 기다린 다음 미리 결정한 원래 메뉴 항목의 오프셋을 사용하여 마우스를 해당 오프셋으로 이동하고 올바른 하위 항목을 클릭합니다. 메뉴 아이템. 아래 코드에서 먼저 셀을 선택할 수있는 기회를 제공합니다.
driver.implicitly_wait(300) # wait up to 300 seconds before calls to find elements time out
driver.get('https://mybinder.org/v2/gh/jupyterlab/jupyterlab-demo/master?urlpath=lab/tree/demo')
driver.execute_script("scroll(0, 0);")
elem = driver.find_element_by_xpath('//div[text()="Run"]')
elem.click() # click on top-level menu item
time.sleep(.2) # wait for sub-menu to appear
action = webdriver.common.action_chains.ActionChains(driver)
action.move_to_element_with_offset(elem, 224, 182)
# click on sub-menu item:
action.click()
action.perform()
업데이트 :보다 최적의 솔루션
driver.implicitly_wait(300) # wait up to 300 seconds before calls to find elements time out
driver.get('https://mybinder.org/v2/gh/jupyterlab/jupyterlab-demo/master?urlpath=lab/tree/demo')
driver.execute_script("scroll(0, 0);")
elem = driver.find_element_by_xpath('//div[text()="Run"]')
elem.click()
driver.implicitly_wait(.2)
elem2 = driver.find_element_by_xpath('//*[contains(text(),"Run Selected Cell and All Below")]')
driver.execute_script("arguments[0].click();", elem2) # sub-menu, however, stays open
# to close the sub-menu menu:
elem.click()
비슷한 속성을 가진 두 개의 li 요소가있는 것 같습니다. xpath
클릭 할 올바른 요소를 식별해야합니다. 올바른 요소 를 클릭 하려면 다음 을 사용하십시오.
xpath_runall = "//ul[@class='lm-Menu-content p-Menu-content']//li[@data-command='notebook:run-all-below']"
element = WebDriverWait(driver, 10).until(
EC.element_to_be_clickable((By.XPATH, xpath_runall))
)
elementText=element.text
print("Found element '{}'".format(elementText))
element.click()
print("Clicked on '{}'".format(elementText))
콘솔 출력 :
Page loaded
Clicked on 'Run'
Found element 'Run Selected Cell and All Below'
Clicked on 'Run Selected Cell and All Below'