【问题标题】:Selenium: How to handle invalid CSS selectors in DOMSelenium:如何处理 DOM 中的无效 CSS 选择器
【发布时间】:2020-06-05 18:28:20
【问题描述】:

我正在用 Selenium / Python3 抓取一个网站,该网站只使用了无效的选择器,例如:

<input id="egg:bacon:SPAM" type="text"/>
<input id="egg:sausages:SPAM:SPAM" type="text"/>

(无效部分为egg:bacon:SPAM & egg:sausages:SPAM:SPAM

我确实尝试使用以下方式选择这些标签:

driver.find_element_by_css_selector('input#egg:bacon:SPAM')

但我当然会得到selenium.common.exceptions.InvalidSelectorException


我也尝试过使用 xpath 来获取我的标签,它适用于:

driver.find_element_by_xpath('//input[@id="egg:bacon:SPAM"]')

但是我的代码是基于一个基于 CSS 选择器的自制库。添加 XPATH 支持需要添加大约 200 行代码(不包括单元测试、文档等),只是为了处理这种错误而不是通用行为。

另外,抓取这个网站是一个更大的项目的一部分,只有这个特定的网站使用那种 CSS 选择器,在 10 上为单个网站付出如此多的努力让我感到不舒服。


我可以使用 find_element_by_css_selector('.foo &gt; input:nth-child(2)') 之类的东西,但它非常棘手,并且 DOM 上的任何小更新都可能破坏刮板。

是否有任何 clean 方法可以通过 Selenium 使用 find_element_by_css_selector 处理无效的 css 选择器,或者我注定要为这个网站使用 XPATH?

【问题讨论】:

    标签: python python-3.x selenium css-selectors


    【解决方案1】:

    它们都有效。您需要转义特殊字符或使用引号:

    driver.find_element_by_css_selector('input[id="egg:bacon:SPAM"]')
    driver.find_element_by_css_selector('input#egg\:bacon\:SPAM')
    

    【讨论】:

      【解决方案2】:

      用包含保留字符的id属性来识别元素,例如egg:bacon:SPAMegg:sausages:SPAM:SPAM您可以使用带有以下通配符的动态

      • ^:表示一个属性值开头
      • *:表示一个属性值包含
      • $:表示属性值结尾

      解决方案

      您可以使用以下解决方案:

      • 识别元素&lt;input id="egg:bacon:SPAM" type="text"/&gt;

        driver.find_element_by_css_selector("input[id^='egg'][id*='bacon'][id$='SPAM']")
        
      • 识别元素&lt;input id="egg:sausages:SPAM:SPAM" type="text"/&gt;

        driver.find_element_by_css_selector("input[id^='egg'][id*='sausages'][id$='SPAM']")
        

      参考

      您可以在以下位置找到一些相关讨论:

      【讨论】:

      • 超级好用,很好用。但是我在同一页面上几乎没有像egg:bacon:SPAMegg:bacon:SPAM:SPAM 这样的输入。据我了解,您的回答器使用一种正则表达式^*$),我担心此方法不支持我在此评论中给出的示例。还有你有一个文档或关键字,所以我可以找到关于这个的文档吗? (+1 反正
      • @Arount ^*$ 不是 正则表达式 :) 而是 通配符css选择器。查看更新的答案并让我知道状态。
      • 谢谢,很高兴知道和超级hepful。我仍然会验证 Sers 的 anwser,因为它不那么冗长(并且在正确的位置使用 replace(':', '\\:') 来完成这项工作),但我继续投票,因为它是非常好的答案(是的,通配符.. ooops :D)
      • 只是为了记录,我刚遇到一种情况,我不得不使用你的通配符,史诗。
      • @Arount 此答案基于您必须在较长时间内适应的最佳实践。
      猜你喜欢
      • 2015-11-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多