この商品のサイズをクロールしようとしています。
問題:製品の色を選択した後にサイズが読み込まれます。
製品ページのソースコードでは、ドロップダウンにonchangeメソッドがあることがわかります。フォーム#postColoronchangeをクリックします。
選択ドロップダウン:
<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&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;">
これはこれまでの私のコードであり、機能していません:
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);
}
});
});
色がクリックされたときにまったく新しいページが読み込まれることが問題だと思います(サイズは動的に追加されません)。
この問題をどのように解決しますか?
これが私のやり方です
_this.evaluate(function() {
$('#select_element_selector').val('value').change();
});
_
change()
は非常に重要です
ページにjQueryがあると仮定します
ここで同じ問題が発生しました。私の解決策は次のとおりです。
casper.then(function(){
this.evaluate(function() {
document.querySelector('select.select-category').selectedIndex = 2; //it is obvious
});
this.capture('screenshot.png');
});
推奨される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に感謝します)。 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はselect
およびaddSelection
コマンドを提供します( https://seleniumhq.github.io/Selenium/docs/api/javascript/index.html )。また、これをネイティブに実装するために、CasperJS GitHubページに保留中の問題チケットを提出しました( https://github.com/n1k0/casperjs/issues/139 )。
これは、casperjsにクレジットカードの詳細を入力するための簡単なコードです。
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');
あなたがあなたの問題の解決策を見つけたかどうかはわかりませんが、これが私がそれを解決する方法です:
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!*/
});
}
トリッキーですが、URLを見ると、Casperはこれをうまく処理できると思います。
このためのコードについてサポートが必要な場合はお知らせください。ただし、少し時間がかかるため、少し疑似コードを提供します。
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をcolor=-9999
。例:
'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'
バニラJavaScriptソリューション(onchangeメソッドのトリガー):
casper.evaluate(function() {
var select_element = document.getElementById('select_element_selector');
select_element.value = 'value';
select_element.onchange();
});
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
})
})
注:マイレージは上記とは異なる場合があります。他の場所で一貫性のない結果が見つかりました。テキスト値は更新されますが、基になるコントロールは起動しません。イライラする!
これを行うための少しハックな方法なし組み込みのキャスパーメソッドを利用して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にありますが、必要に応じてVanillaJS用に編集できます。通常のforループは、capserのキューイングシステムで問題が発生するため、再帰関数を使用する必要があります。