【问题标题】:How to click a "select option" and then evaluate loaded content with casperjs如何单击“选择选项”,然后使用 casperjs 评估加载的内容
【发布时间】:2013-05-02 07:10:04
【问题描述】:

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

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 表单,点击更改:

<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);
        }
    });
});

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

你会如何解决这个问题?

【问题讨论】:

    标签: javascript phantomjs html-select casperjs


    【解决方案1】:

    我就是这样做的

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

    change() 很重要

    我假设你的页面上有 jQuery

    【讨论】:

    • 这对我不起作用。它在视觉上更改了选项下拉列表(可以通过 casper.capture 看到),但实际上并不会触发所选值。
    • 非常感谢
    【解决方案2】:

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

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

    【讨论】:

    • 我尝试使用鼠标元素,但您的解决方案似乎更好。
    • 只需尝试代码获取我想要的数据。
    【解决方案3】:

    推荐的 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)。

    【讨论】:

      【解决方案4】:

      这是在 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');
      

      【讨论】:

        【解决方案5】:

        棘手,但看看 URL,我认为 Casper 可以很好地处理这个问题。

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

        • 创建一个包含颜色和颜色 ID 的空对象 { color: colorId }
        • 正如您已经在做的那样,找到带有 [name='color'] 的选择菜单并循环浏览这些选项。将任何值不为 0 的内容推送到您的对象
        • 编写一个新函数,该函数将转到 URL http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&amp;color=-9999&amp;size=0&amp;addbread=OUTLET&amp;addbread2=DRIZIA&amp;currentimage=1&amp;selectedmi=a1_INDEX_14&amp;prev=10850-4314&amp;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'

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

        【讨论】:

          【解决方案6】:

          我不知道您是否找到了解决问题的方法,但我将如何解决它:

          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!*/
             });
          
          }
          

          【讨论】:

            【解决方案7】:

            使用内置 casper 方法的 jQuery 实现这一点的一个稍微有点老套的方法是:

            // 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 的排队系统中遇到困难。

            【讨论】:

              【解决方案8】:

              tejesh95 的解决方案对我进行了一些小改动,#1 我无法让 findElementById 工作,因此将其切换为 'document.querySelector('#selectorId)' 。我还必须将“onchange”更改为“onclick”。这是 casperjs 测试工具中的代码:

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

              })

              请注意:您的里程可能与上述有所不同,我在其他地方发现不一致的结果,文本值会更新,但底层控件不会触发。令人沮丧!

              【讨论】:

                【解决方案9】:

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

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

                【讨论】:

                  猜你喜欢
                  • 1970-01-01
                  • 2012-10-11
                  • 1970-01-01
                  • 2021-11-07
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-10-02
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多