javascript 如何单击“选择选项”,然后使用 casperjs 评估加载的内容
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16332312/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to click a "select option" and then evaluate loaded content with casperjs
提问by 2083
I'm trying to crawl the sizes for this product:
我正在尝试抓取此产品的尺寸:
The problem: The sizes are loaded after the color of the product is selected.
问题:选择产品颜色后加载尺寸。
In the product page's source code, I can see that the dropdown has a onchange-method: It clicks the form #postColor onchange.
在产品页面的源代码中,我可以看到下拉菜单有一个 onchange 方法:它点击表单 #postColor onchange。
The select dropdown:
选择下拉列表:
<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>
The #postColor form, which is clicked onchange:
#postColor 表单,点击后更改:
<input type="submit" name="postColor" value="" onclick="location.href=('./?model=10344-4180&color='+document.forms[0].color.value+'&size='+document.forms[0].size.value+'&addbread=OUTLET&addbread2=DRIZIA&currentimage='+document.getElementById('currentimage').value+'&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183'); return false;" id="postColor" class="cpobutton " style="display: none;">
This is my code so far and it's not working:
到目前为止,这是我的代码,但它不起作用:
casper.start('http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&addbread=OUTLET&addbread2=DRIZIA&color=0¤timage=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);
}
});
});
I suspect that problem is that a totally new page is loaded when a color is clicked (the sizes are not dynamically appended).
我怀疑这个问题是点击颜色时加载了一个全新的页面(尺寸不是动态附加的)。
How would you solve this problem?
你会如何解决这个问题?
回答by wmarbut
This is how I do it
这就是我的做法
this.evaluate(function() {
$('#select_element_selector').val('value').change();
});
The change()
is very important
将change()
是非常重要的
I'm assuming that you have jQuery on the page
我假设您在页面上有 jQuery
回答by Valery Lyatsevich
Got same issue here. My solution is:
这里有同样的问题。我的解决办法是:
casper.then(function(){
this.evaluate(function() {
document.querySelector('select.select-category').selectedIndex = 2; //it is obvious
});
this.capture('screenshot.png');
});
回答by tfmontague
The recommended jQuery solution doesn't actually work for me.
推荐的 jQuery 解决方案实际上对我不起作用。
casper.evaluate(function() {
$('#select_element_selector').val('value').change();
});
While, the capture()
command shows the select option as selected visually, it doesn't actually trigger the event. Try using this with the waitForText()
command for example; the program will timeout.
虽然该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();
What did work for me, was the code provided below (thanks @ArtjomB). How to fill a select element which is not embedded in a form with CasperJS?
对我有用的是下面提供的代码(感谢@ArtjomB)。 如何使用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');
Although, I think CasperJS should provide native support to select options from a drop-down when they aren't apart of a form (http://docs.casperjs.org/en/latest/modules/index.html). Selenium offers the select
and addSelection
commands (https://seleniumhq.github.io/selenium/docs/api/javascript/index.html). I've also filed a pending issue ticket on the CasperJS GitHub page to implement this natively (https://github.com/n1k0/casperjs/issues/1390).
虽然,我认为 CasperJS 应该提供原生支持,以便在它们不属于表单(http://docs.casperjs.org/en/latest/modules/index.html)时从下拉列表中选择选项。Selenium 提供select
和addSelection
命令(https://seleniumhq.github.io/selenium/docs/api/javascript/index.html)。我还在 CasperJS GitHub 页面上提交了一个待处理的问题单,以在本地实现它(https://github.com/n1k0/casperjs/issues/1390)。
回答by Ravishankar
this is simple code to enter credit card details in casper js
这是在 casper js 中输入信用卡详细信息的简单代码
casper.evaluate(function(CC,security_code) {
casper.evaluate(函数(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');
回答by tejesh95
vanilla javascript solution (triggering onchange method):
vanilla javascript 解决方案(触发 onchange 方法):
casper.evaluate(function() {
var select_element = document.getElementById('select_element_selector');
select_element.value = 'value';
select_element.onchange();
});
回答by George Worthington
tejesh95's solution worked for me with a few minor changes, #1 I couldn't get findElementById to work so switched it to 'document.querySelector('#selectorId)' . I also had to change 'onchange' to 'onclick'. Here's the code within the casperjs test harness:
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
})
})
})
Follow on note: Your mileage may vary on the above, I found inconsistent results elsewhere, the text value would update, but the underlying control wouldn't fire. Frustrating!
请注意:您的里程可能与上述有所不同,我在其他地方发现不一致的结果,文本值会更新,但底层控件不会触发。令人沮丧!
回答by Ruskin
A slightly hacky way to do this withoutusing jQuery utilising built-in casper methods is:
在不使用 jQuery 的情况下使用内置的 casper 方法来做到这一点的一种稍微有点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);
};
This is in TypeScript but you can edit for vanilla JS if you need to. You need to use a recursive function because a normal for loop gets into difficulties with capser's queuing system.
这是在 TypeScript 中,但如果需要,您可以为 vanilla JS 进行编辑。您需要使用递归函数,因为普通的 for 循环在使用 capser 的排队系统时会遇到困难。
回答by imjared
Tricky, but looking at the URL, I think Casper can handle this nicely.
棘手,但查看 URL,我认为 Casper 可以很好地处理这个问题。
Let me know if you need help with the code for this but it will take a bit longer so to give you a bit of pseudo-code,
如果您需要有关代码的帮助,请告诉我,但需要更长的时间,因此给您一些伪代码,
- create an empty object of colors and color IDs { color: colorId }
- as you're already kind of doing, find the select menu with [name='color'] and loop through those options. push anything that doesn't have a value of 0 to your object
- write a new function that will go to the url
http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=-9999&size=0&addbread=OUTLET&addbread2=DRIZIA¤timage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183
and substitute the color ID wherecolor=-9999
.
- 创建颜色和颜色 ID 的空对象 { color: colorId }
- 正如您已经在做的那样,找到带有 [name='color'] 的选择菜单并循环浏览这些选项。将任何值不为 0 的内容推送到您的对象
- 编写一个新函数,该函数将转到 url
http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=-9999&size=0&addbread=OUTLET&addbread2=DRIZIA¤timage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183
并替换颜色 ID wherecolor=-9999
。
example:
'http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=' + object.colorId + '&size=0&addbread=OUTLET&addbread2=DRIZIA¤timage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183'
例子:
'http://shop.baumundpferdgarten.com/showmodel/?model=10344-4180&color=' + object.colorId + '&size=0&addbread=OUTLET&addbread2=DRIZIA¤timage=1&selectedmi=a1_INDEX_14&prev=10850-4314&next=10413-4183'
- Either add the sizes to the existing colors object or make a new one, or console.log them. The world is yours!
- 将大小添加到现有颜色对象或创建一个新对象,或使用 console.log 记录它们。世界是你的!
回答by Fabio
I don't know if you found a solution to your problem, but here is how I would solve it:
我不知道您是否找到了解决问题的方法,但这是我的解决方法:
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!*/
});
}