如何单击“选择选项”,然后使用casperjs评估加载的内容

时间:2013-05-02 07:10:05

标签: javascript phantomjs html-select casperjs

我正在尝试抓取此产品的尺寸:

Link to product

问题:选择产品颜色后会加载尺寸。

在产品页面的源代码中,我可以看到下拉列表中有一个onchange-method:它点击了#postColor onchange形式。

选择下拉列表:

<select name="color" id="color" class="cposelect" onchange="document.getElementById('postColor').click();" style="width:150px;margin-right: 20px; float: left;">
    <option selected="selected" onfocus="if (this.storeCurrentControl != null) storeCurrentControl(event, this);" value="0">Select colour</option>
    <option onfocus="if (this.storeCurrentControl != null) storeCurrentControl(event, this);" value="-8027">Light Camel</option>
    <option onfocus="if (this.storeCurrentControl != null) storeCurrentControl(event, this);" value="-9999">black</option>
</select>

#postColor表单,单击onchange:

<input type="submit" name="postColor" value="" onclick="location.href=('./?model=10344-4180&amp;color='+document.forms[0].color.value+'&amp;size='+document.forms[0].size.value+'&amp;addbread=OUTLET&amp;addbread2=DRIZIA&amp;currentimage='+document.getElementById('currentimage').value+'&amp;selectedmi=a1_INDEX_14&amp;prev=10850-4314&amp;next=10413-4183'); return false;" id="postColor" class="cpobutton " style="display: none;">

到目前为止,这是我的代码,但它无效:

casper.start('http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&addbread=OUTLET&addbread2=DRIZIA&color=0&currentimage=1&selectedmi=a1_INDEX_14', function() {
    this.test.assertExists('select[name="color"] option:nth-child(2)');
    this.click('select[name="color"] option:nth-child(2)');
    this.waitForSelector('select[name="size"] option:nth-child(2)', function() {
        this.test.pass('selector is !');
        var sizes = this.evaluate(function() {
            console.log("======== evaluating ========");
            // var sizes = document.querySelectorAll('#size option');
            return document.querySelectorAll('#size option');
        });
        for (var i = sizes.length - 1; i >= 0; i--) {
            console.log(sizes[i].innerText);
        }
    });
});

我怀疑问题是在点击颜色时会加载一个全新的页面(不会动态附加大小)。

你会如何解决这个问题?

9 个答案:

答案 0 :(得分:14)

我就是这样做的

this.evaluate(function() {
    $('#select_element_selector').val('value').change();
});

change()非常重要

我假设你在页面上有jQuery

答案 1 :(得分:12)

这里有同样的问题。我的解决方案是:

casper.then(function(){
    this.evaluate(function() {
        document.querySelector('select.select-category').selectedIndex = 2; //it is obvious
    });
    this.capture('screenshot.png');
});

答案 2 :(得分:4)

推荐的jQuery解决方案实际上并不适用于我。

casper.evaluate(function() {
    $('#select_element_selector').val('value').change();
});

虽然capture()命令显示了可视选择的选项,但它实际上并没有触发事件。例如,尝试使用waitForText()命令;程序将超时。

casper
  .start('http://factfinder.census.gov/faces/tableservices/jsf/pages/productview.xhtml?pid=DEC_00_SF1_DP1&prodType=table')
  .waitForText('Add/Remove Geographies', function () {
    casper.click('#addRemoveGeo_btn');
  })
  .waitForText('Select a geographic type:', function () {
    casper.evaluate(function () {
      $('#summaryLevel').val('050').change();
    });
  })
  .waitForText('Select a state:', function () {
    casper.capture('test.png');
  })
  .run();

对我有用的是下面提供的代码(感谢@ArtjomB)。 How to fill a select element which is not embedded in a form with CasperJS?

casper.selectOptionByValue = function(selector, valueToMatch){
    this.evaluate(function(selector, valueToMatch){
        var select = document.querySelector(selector),
            found = false;
        Array.prototype.forEach.call(select.children, function(opt, i){
            if (!found && opt.value.indexOf(valueToMatch) !== -1) {
                select.selectedIndex = i;
                found = true;
            }
        });
        // dispatch change event in case there is some kind of validation
        var evt = document.createEvent("UIEvents"); // or "HTMLEvents"
        evt.initUIEvent("change", true, true);
        select.dispatchEvent(evt);
    }, selector, valueToMatch);
};

casper.selectOptionByValue('#summaryLevel', '050');

虽然,我认为CasperJS应该提供原生支持,以便在它们不是表格(http://docs.casperjs.org/en/latest/modules/index.html)时从下拉菜单中选择。 Selenium提供selectaddSelection命令(https://seleniumhq.github.io/selenium/docs/api/javascript/index.html)。我还在CasperJS GitHub页面上提交了待处理的发票,以便本地实现(https://github.com/n1k0/casperjs/issues/1390)。

答案 3 :(得分:1)

这是在casper js中输入信用卡详细信息的简单代码

casper.evaluate(function(CC,security_code){

      document.querySelector('input#receipt_creditcard_number').value = CC;
      document.querySelector('select#receipt_creditcard_month').selectedIndex = 10;
      document.querySelector('select#receipt_creditcard_year').selectedIndex = 10;
      document.querySelector('input#receipt_creditcard_verification_value').value = security_code;
      document.querySelector('input#receipt_save_creditcard_in_profile').click();
  }, '4242424242424242','123');

答案 4 :(得分:0)

Tricky,但是看看网址,我认为Casper可以很好地处理这个问题。

如果您需要有关此代码的帮助,请告诉我,但需要更长时间才能给您一些伪代码,

  • 创建一个颜色和颜色ID {color:colorId}
  • 的空对象
  • 正如您已经做的那样,找到[name ='color']的选择菜单并循环浏览这些选项。将任何没有值0的东西推送到你的对象
  • 编写一个新功能,该功能将转到网址http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=-9999&size=0&addbread=OUTLET&addbread2=DRIZIA&currentimage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183,并将颜色ID替换为color=-9999
  

示例:

     

'http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=' + object.colorId + '&size=0&addbread=OUTLET&addbread2=DRIZIA&currentimage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183'

  • 将大小添加到现有颜色对象或创建一个新对象,或者控制它们。世界是你的!

答案 5 :(得分:0)

我不知道你是否找到了问题的解决方案,但我将如何解决这个问题:

casper.click('#color');
casper.then(function() {
casper.waitFor(function check() {
  return this.evaluate(function() {
    return document.querySelector('select.select-category').selectedIndex === 2; 
  });
}, function then() {
     /* do the rest that you would want to do!*/
   });

}

答案 6 :(得分:0)

使用内置的casper方法使用jQuery 没有这样做的一个有点hacky的方法是:

// Assumes the select box is on the first item at index 0
chooseSelectOption = (friendlyName : string, selectLocator : string, optionIndex : number) => {
    casper.test.assertExists(selectLocator, "then select index " + optionIndex + " in the " + friendlyName + " select box");
    casper.click(selectLocator);
    this.goDown(selectLocator, optionIndex);
};

// recursive funtion to go down various levels
private goDown = (locator: string, depth : number, currentLevel : number = 0) => {
    if (currentLevel >= depth) { return; }
    casper.sendKeys(locator, casper.page.event.key.Down, { keepFocus: true });
    this.goDown(locator, depth, currentLevel + 1);
};

这是在TypeScript中,但如果需要,您可以编辑vanilla JS。你需要使用递归函数,因为正常的for循环会遇到capser的排队系统。

答案 7 :(得分:0)

vanilla javascript解决方案(触发onchange方法):

casper.evaluate(function() {
    var select_element = document.getElementById('select_element_selector');
    select_element.value = 'value';
    select_element.onchange();
});

答案 8 :(得分:0)

tejesh95的解决方案为我工作了一些小的改动,#1我无法使findElementById工作,所以切换到&#39; document.querySelector(&#39; #selectorId)& #39; 。我还必须改变“改变”。到&#39; onclick&#39;。这是casperjs测试工具中的代码:

casper.then(function() {
  this.evaluate(function() {
  var select_element = document.querySelector('#selectorId')
  select_element.value = 'stringValue'
  select_element.onclick
})

})

请注意:您的里程可能因上述情况而有所不同,我发现其他地方的结果不一致,文本值会更新,但基础控制不会触发。令人沮丧!