【问题标题】:Is there a way to select an item on a webpage with Selenium with no unique ID?有没有办法在没有唯一 ID 的 Selenium 网页上选择一个项目?
【发布时间】:2021-07-26 17:11:33
【问题描述】:

我的目标是打开一个网页,然后单击特定应用的应用按钮,例如 Anaplan。过去,我使用 CSS 选择器获取元素,结合类和 ID,as shown in this past post

first_item = driver.find_element_by_id("anaplan")

我遇到了一个网页,其中的按钮似乎没有任何 ID 或唯一值:

Anaplan App 按钮的 HTML 输出:

<a
  aria-label="launch app Anaplan"
  class="chiclet a--no-decoration"
  data-se="app-card"
  href="https://gartner.okta.com/home/anaplan/0oaforg08lyATdLuw4x6/2487"
  draggable="true"
  ><article class="chiclet--article">
    <button
      class="chiclet--action"
      tabindex="0"
      aria-label="Settings for Anaplan"
      data-se="app-card-settings-button"
    >
      <svg
        class="chiclet--action-kebab"
        width="20"
        height="4"
        viewBox="0 0 20 4"
        fill="#B7BCC0"
        xmlns="http://www.w3.org/2000/svg"
      >
        <circle cx="2" cy="2" r="2"></circle>
        <circle cx="10" cy="2" r="2"></circle>
        <circle cx="18" cy="2" r="2"></circle>
      </svg>
    </button>
    <section class="chiclet--main" data-se="app-card-main">
      <img
        class="chiclet--main-logo"
        src="https://ok11static.oktacdn.com/fs/bcg/4/gfs1ev15ab63zqgZ91d8"
        alt="Anaplan logo"
      />
    </section>
    <footer class="chiclet--footer" data-se="app-card-footer">
      <o-tooltip content="Anaplan" position="bottom" class="hydrated"
        ><div slot="content"></div>
        <div aria-describedby="o-tooltip-0">
          <h1 class="chiclet--app-title" data-se="app-card-title">Anaplan</h1>
        </div>
      </o-tooltip>
    </footer>
  </article>
</a>

我抓取了 Anaplan 按钮的 Xpath,显示如下:

/html[@class='hydrated wf-proximanova-n4-inactive wf-
inactive']/body[@class='default']/div[@id='root']
/div[@class='enduser-app ']/section[@class='content-frame']
/main[@class='main-container has-top-bar']/div[@class='dashboard--main']/section[@id='main- 
content']/section[@class='chiclet-area']
/section[@class='chiclet-grid--container']
/section/section[@class='chiclet-grid section-appear-done section-enter-done']
/a[@class='chiclet a--no-decoration'][1]/article[@class='chiclet--article']

应用程序之间的唯一区别是括号中的数字: /a[@class='chiclet a--no-decoration'][1],其中 1 似乎是 Anaplan,3 是 G Drive,依此类推。有没有办法选择像这样似乎根本没有唯一标识符的元素?

【问题讨论】:

    标签: python python-3.x selenium web-scraping


    【解决方案1】:

    要找到第一个按钮,您可以使用以下xpaths //a[@aria-label='launch app Anaplan']//a[contains(@href,'anaplan')] 之一,还有许多其他独特的组合。 css selectors也可以这样做
    与上述类似,您在此处提供的所有其他导航按钮也有多种组合。
    如果元素位于 &lt;iframe&gt; 内,您必须先切换到 &lt;iframe&gt;,然后再退出。
    使用
    iframe = driver.find_element_by_xpath("//iframe[@name='iframeName']") 或其匹配的任何定位器找到&lt;iframe&gt;
    然后switch_to&lt;iframe&gt;:
    driver.switch_to.frame(iframe)
    如果在那之后您需要在&lt;iframe&gt; 之外的任何地方继续操作,请使用
    driver.switch_to.default_content()

    【讨论】:

    • //a[contains(@href,'anaplan')] 完美运行。但是,当该页面包含 iframe 时,它​​似乎不适用于另一个页面,如下面的粘贴所示。//a[contains(@href,'401068')] 例如返回错误,因为无法找到元素,即使 HTML 中的 href 肯定有 pastebin.com/D5Fzn6hu
    • 我将答案更新为&lt;iframe&gt;问题
    【解决方案2】:

    xpath 和 css 都可以。 xpath 示例:

    Anaplan:

    //a[contains(@aria-label, 'Anaplan')]/article/button
    

    或者:

    //button[contains(@aria-label, 'Settings for Anaplan')]
    

    垃圾邮件隔离区:

    //a[contains(@aria-label, 'Spam Quarantine')]
    

    G-套房

    //a[contains(@aria-label, 'G Suite Drive')]
    

    主要思想是你可以通过写一个属性的部分名称来找到一个元素。

    更新:

    如果一个元素位于 iframe 中,您应该等待它加载并切换到它。 Selenium 有非常方便的方法:frame_to_be_available_and_switch_to_it

    from selenium.webdriver.common.by import By
    from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.support.wait import WebDriverWait
    
    driver = webdriver.Chrome()
    driver.get(url)
    wait = WebDriverWait(driver, 15)
    wait.until(EC.frame_to_be_available_and_switch_to_it((By.CSS_SELECTOR, "iframe[data-testid=shell-content]")))
    

    切换到 iframe 后,您可以使用其中的元素。

    【讨论】:

    • 所有这些都有效。但似乎也不适用于 iframe,类似于其他解决方案。 iframe 有什么不同吗? pastebin.com/D5Fzn6hu
    猜你喜欢
    • 2019-06-11
    • 2018-07-11
    • 1970-01-01
    • 2021-08-26
    • 1970-01-01
    • 2015-07-30
    • 2016-10-23
    • 1970-01-01
    • 2012-11-04
    相关资源
    最近更新 更多