एक jupyterhub पृष्ठ में अजगर-सेलेनियम के साथ एक मौजूदा HTML तत्व कैसे खोजें?

Dec 10 2020

मेरे पास HTML पृष्ठ में निम्न निर्माण हैं और मैं liतत्व का चयन करना चाहता हूं (अजगर-सेलेनियम के साथ):

<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 मोजावे (10.14.6)
  • अजगर 3.8.6
  • सेलेनियम 3.8.0
  • geckodriver 0.26.0

परिशिष्ट

मैं फ़ायरफ़ॉक्स "सेलेनियम आईडीई" ऐड-ऑन के साथ चरणों को रिकॉर्ड करने की कोशिश कर रहा हूं, जो कि पायथन के लिए निम्नलिखित चरण देता है:

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

जवाब

4 DebanjanB Dec 18 2020 at 02:37

आप काफी करीब थे। वास्तव में आपके पूरे कार्यक्रम में केवल एक ही मुद्दा था:

  • xpath_runall = "//li[@data-command='notebook:run-all-below']"के रूप में पाठ के साथ दिखाई तत्व की पहचान नहीं करता नीचे भागो चयनित सेल और सभी विशिष्ट के रूप में सबसे पहले मिलने वाला तत्व एक है छिपा हुआ तत्व।

अतिरिक्त मुद्दो पर विचार करना

कुछ और अनुकूलन:

  • तत्व की पहचान xpath = "//button[@title='Save the notebook contents and create checkpoint']"एक क्लिक करने योग्य तत्व के रूप में की जाती है । इसलिए चुनाव आयोग के बजाय जैसा कि presence_of_element_located()आप उपयोग कर सकते हैंelement_to_be_clickable()

  • एक बार जब तत्व ईसी के माध्यम से वापस आ जाता है 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']
    
  • चूंकि एप्लिकेशन जावास्क्रिप्ट के माध्यम से बनाया गया है, इसलिए आपको एक्शनचिन्स का उपयोग करने की आवश्यकता है ।


उपाय

आपका अनुकूलित समाधान होगा:

  • कोड ब्लॉक:

    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
    
3 Booboo Dec 17 2020 at 23:21

इसने मेरे लिए काम किया। मैं पूर्ण 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()
1 KunduK Dec 10 2020 at 19:58

ऐसा लगता है कि समान विशेषताओं वाले दो ली तत्व हैं। आपको सही तत्व 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'