Capybara选择选项

时间:2018-03-10 16:47:48

标签: ruby drop-down-menu web-scraping phantomjs capybara

我试图使用Capybara和PhantomJS进行刮刀时,我必须查找一些项目,当您与3个下拉菜单进行交互时,第一个下拉列表为您提供第二个下拉菜单的选项,第二个下拉列表为您提供第三个选项,所以,这是我的问题,我已经在第一个下拉列表中列出了选项,但是当我点击第一个元素时,循环停止,并且没有执行其他选项下拉菜单。

这是我的代码。

find(:xpath, "//a[contains(@id, 'filterBrand-button')]").click
all(:xpath , "//*[contains(@id, 'filterBrand')]")[1].all('*').each do|option|
  if option.text != '-- Select --'
    puts option.text        
    option.click
    sleep(2)        
    find(:xpath, "//a[contains(@id, 'filterModel-button')]").trigger('click')
    sleep(2)       
     all(:xpath , "//*[contains(@id, 'filterModel')]")[0].all('*').each do|option2|
       if option2.text != '-- Select --'
         puts option2.text
         option2.click 
         find(:xpath, "//a[contains(@id, 'filterVersion-button')]").trigger('click')
         sleep(4)        
         all(:xpath , "//*[contains(@id, 'filterVersion')]")[0].all('*').each do|option3|
           if option3.text != '-- Select --'
             option3.click
             puts option3.text
           end
         end
       end
     end  
  end

我使用sleep命令等到下拉列表加载选项,但在option.click之后代码在输出中没有显示任何内容

HTML代码就是这样。

<form name="searchForm" id="searchForm" action="http://search_action" method="POST" name="searchform">                                                                                              
  <p>
  <label class="left" for="filterBrand"> Marca </label>
  <select style="font-size:73%;" name="filterBrand" id="filterBrand" class="combo">
  </select>
   </p>
   <p>
   <label class="left" for="filterModel"> Modello</label>
   <select  style="font-size:73%;" onchange="searchProduct();" name="filterModel" id="filterModel" class="combo">                                                             
   </select>
   </p>
   <p>
   <label class="left" for="filterVersion">Versione</label>
   <select style="font-size:73%;" onchange="searchProduct();" name="filterVersion" id="filterVersion" class="combo">
   </select>               
   </p>

如您所见,下拉列表中没有选项,单击此选项后会加载此选项。正如我在第一个问题中所写的那样,问题是,除了第一个下拉选择中的第一个选项之外,capybara在任何选项中都不执行click方法;但如果您对点击方法发表评论,则可以看到打印完整的选项列表。

所以,我能说的是,在调用click方法之后,循环被中断,或者是我在几次执行中可以观察到的。

1 个答案:

答案 0 :(得分:0)

你在这里遇到的问题是你正在使用all但没有传递任何关于你希望它返回多少元素的指示。这意味着0个元素是可接受的数字,因为在第一次选择之后没有选项(直到AJAX请求返回,所以整个页面没有被完全替换,或者你将拥有过时的元素,我假设?){{ 1}}只会返回一个空数组。最简单的解决方案是告诉all您希望返回最少数量的元素

all

注意:由于https://github.com/teamcapybara/capybara#beware-the-xpath--trap而使用find(:xpath, ".//a[contains(@id, 'filterBrand-button')]").click all(:xpath , ".//*[contains(@id, 'filterBrand')]")[1].all('*', minimum: 2).each do |option| # Assuming you'll see `-- Select --` and at least one other if option.text != '-- Select --' puts option.text option.click find(:xpath, ".//a[contains(@id, 'filterModel-button')]").trigger('click') all(:xpath , ".//*[contains(@id, 'filterModel')]", minimum: 1)[0].all('*', minimum: 2).each do|option2| if option2.text != '-- Select --' puts option2.text option2.click find(:xpath, ".//a[contains(@id, 'filterVersion-button')]").trigger('click') # Needing to use trigger here is a red flag all(:xpath , ".//*[contains(@id, 'filterVersion')]", minimum: 1)[0].all('*', minimum: 2).each do|option3| if option3.text != '-- Select --' option3.click puts option3.text end end end end end 启动每个XPath选择器。此外,我确信你可以使用的选择器可以使这个读取更好并清理它,但是如果没有实际HTML的例子,就不可能为此提出建议。可以在没有HTML的情况下进行的一个清理建议是将“ - 选择 - ”检查移动到Capybara查询中

.//

更新:既然你已经添加了HTML(假设按钮ID是准确的,并且真的不需要find(:xpath, "//a[contains(@id, 'filterBrand-button')]").click all(:xpath , "//*[contains(@id, 'filterBrand')]")[1].all('*', minimum: 1, text: /^((?!-- Select --).)*$/).each do |option|# Element with `-- Select --` won't be matched so now minimum: 1 puts option.text option.click find(:xpath, "//a[contains(@id, 'filterModel-button')]").trigger('click') all(:xpath , "//*[contains(@id, 'filterModel')]", minimum: 1)[0].all('*', minimum: 1, text: /^((?!-- Select --).)*$/).each do|option2| puts option2.text option2.click find(:xpath, "//a[contains(@id, 'filterVersion-button')]").trigger('click') # Needing to use trigger here is a red flag all(:xpath , "//*[contains(@id, 'filterVersion')]", minimum: 1)[0].all('*', minimum: 2, text: /^((?!-- Select --).)*$/).each do|option3| option3.click puts option3.text end end end ,这将更清晰地写为

contains