等待来自 CasperJS 中选择 <select> 字段的 AJAX 响应
Waiting for AJAX response from a selection of a <select> field in CasperJS
我想用 CasperJS 抓取这个网站:
http://www.agoda.com/hotel-des-arts-saigon-mgallery-collection/hotel/ho-chi-minh-city-vn.html?checkin=2015-11-14&los=2&adults=2&childs=0&rooms=1
我想通过 CasperJS 更改货币选项。但是,货币选项包含在 <select></select>
标签中,该标签未嵌入表单中。当我随后阅读 table 时,它显示的是旧货币的价格。当货币更改时,价格通过 AJAX 加载。
如何使用 CasperJS?
这是我的代码:
var casper = require("casper").create({
verbose: true,
logLevel: 'error',
pageSettings: {
loadImages: false,
}
});
var utils = require('utils');
var url = 'http://www.agoda.com/hotel-des-arts-saigon-mgallery-collection/hotel/ho-chi-minh-city-vn.html?checkin=2015-11-14&los=4&adults=2&childs=0&rooms=1';
var names = [];
var prices = [];
var currency = [];
function getName() {
var rows = document.querySelectorAll('table#room-grid-table tbody tr td:first-child .info-container .room-name span');
return Array.prototype.map.call(rows, function(e) {
return e.innerHTML;
});
}
function getPrice() {
var price = document.querySelectorAll('table#room-grid-table tbody tr td:nth-child(3) .price span.sellprice');
return Array.prototype.map.call(price, function(e) {
return e.innerHTML;
});
}
casper.start(url, function() {
this.echo(this.getTitle());
});
casper.then(function() {
this.click('select[id="currency-options"]');
});
casper.then(function() {
this.click('option[value="AED"]');
});
casper.then(function() {
names = this.evaluate(getName);
prices = this.evaluate(getPrice);
});
casper.then(function() {
utils.dump(names);
utils.dump(prices);
})
casper.run();
Select 框:
<select id="currency-options" data-selenium="room-currency">
<option value="AED">Arab Emirates Dirham (AED)</option>
<option value="ARS">Argentine Peso (ARS)</option>
...
<option value="USD" selected="">US Dollar (USD)</option>
</select>
Table:
<table id="room-grid-table">
<tbody data-selenium="room-tbody" data-prebook-url="/NewSite/en-us/Hotel/Prebook/929399">
<tr>
<td>...</td>
<td>...</td>
<td>
<div class="price" data-selenium="price">
<span class="currency" data-selenium="price-currency">USD</span>
<span class="crossout show-cor-tooltip">288.75</span>
<span class="sellprice">187.11</span>
</div>
</td>
</tr>
<tr>...</tr>
...
</tbody>
</table>
单击 select 框的选项字段几乎不起作用,因为它不是 PhantomJS 中的可单击 UI 元素。您必须通过 DOM 以编程方式 select 您想要的选项。例如,这可以通过将 selectElement.selectedIndex
属性 设置为正确的索引来完成。设置好后,需要在select元素上触发change事件,否则不会向服务器发送AJAX请求。
这是从我的 :
复制的代码
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);
};
更改货币设置后需要等待AJAX请求完成。这可以通过不同的方式完成:
静态等待时间 有效,但等待时间可能比请求需要的时间长:
casper.wait(5000);
等待特定的 select 或 出现效率更高,因为一旦 select 或被发现。例如,您可以等待 table 中的货币文本更改。这可以使用 XPath 轻松完成:
var x = require('casper').selectXPath;
var currency = 'AED';
...
casper.waitForSelector(x("//*[@id='room-grid-table']//*[@class='currency' and contains(text(), '"+currency+"')]"));
您可以等待特定select或table中的货币的文本更改。如果更改是即时的,这将不起作用,因为 CasperJS 需要一点时间来接受更改。 20ms应该够了。
casper.waitForSelectorTextChange("#room-grid-table .currency");
等待 AJAX 响应,它通过查看所有收到的资源来工作:
casper.waitForResource("Main/GetRoomTypeDetailList").wait(50);
版本 2 的完整脚本:
var casper = require("casper").create({
verbose: true,
logLevel: 'error',
pageSettings: {
loadImages: false,
}
});
var utils = require('utils');
var x = require('casper').selectXPath;
var url = 'http://www.agoda.com/hotel-des-arts-saigon-mgallery-collection/hotel/ho-chi-minh-city-vn.html?checkin=2015-11-14&los=4&adults=2&childs=0&rooms=1';
var names = [];
var prices = [];
var currency = [];
function getName() {
var rows = document.querySelectorAll('table#room-grid-table tbody tr td:first-child .info-container .room-name span');
return Array.prototype.map.call(rows, function(e) {
return e.innerHTML;
});
}
function getPrice() {
var price = document.querySelectorAll('table#room-grid-table tbody tr td:nth-child(3) .price span.sellprice');
return Array.prototype.map.call(price, function(e) {
return e.innerHTML;
});
}
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.start(url, function() {
this.echo(this.getTitle());
});
var currency = 'AED';
casper.then(function() {
this.selectOptionByValue('select[id="currency-options"]', currency);
});
casper.waitForSelector(x("//*[@id='room-grid-table']//*[@class='currency' and contains(text(), '"+currency+"')]"));
casper.then(function() {
names = this.evaluate(getName);
prices = this.evaluate(getPrice);
});
casper.then(function() {
utils.dump(names);
utils.dump(prices);
})
casper.run();
我想用 CasperJS 抓取这个网站: http://www.agoda.com/hotel-des-arts-saigon-mgallery-collection/hotel/ho-chi-minh-city-vn.html?checkin=2015-11-14&los=2&adults=2&childs=0&rooms=1
我想通过 CasperJS 更改货币选项。但是,货币选项包含在 <select></select>
标签中,该标签未嵌入表单中。当我随后阅读 table 时,它显示的是旧货币的价格。当货币更改时,价格通过 AJAX 加载。
如何使用 CasperJS?
这是我的代码:
var casper = require("casper").create({
verbose: true,
logLevel: 'error',
pageSettings: {
loadImages: false,
}
});
var utils = require('utils');
var url = 'http://www.agoda.com/hotel-des-arts-saigon-mgallery-collection/hotel/ho-chi-minh-city-vn.html?checkin=2015-11-14&los=4&adults=2&childs=0&rooms=1';
var names = [];
var prices = [];
var currency = [];
function getName() {
var rows = document.querySelectorAll('table#room-grid-table tbody tr td:first-child .info-container .room-name span');
return Array.prototype.map.call(rows, function(e) {
return e.innerHTML;
});
}
function getPrice() {
var price = document.querySelectorAll('table#room-grid-table tbody tr td:nth-child(3) .price span.sellprice');
return Array.prototype.map.call(price, function(e) {
return e.innerHTML;
});
}
casper.start(url, function() {
this.echo(this.getTitle());
});
casper.then(function() {
this.click('select[id="currency-options"]');
});
casper.then(function() {
this.click('option[value="AED"]');
});
casper.then(function() {
names = this.evaluate(getName);
prices = this.evaluate(getPrice);
});
casper.then(function() {
utils.dump(names);
utils.dump(prices);
})
casper.run();
Select 框:
<select id="currency-options" data-selenium="room-currency">
<option value="AED">Arab Emirates Dirham (AED)</option>
<option value="ARS">Argentine Peso (ARS)</option>
...
<option value="USD" selected="">US Dollar (USD)</option>
</select>
Table:
<table id="room-grid-table">
<tbody data-selenium="room-tbody" data-prebook-url="/NewSite/en-us/Hotel/Prebook/929399">
<tr>
<td>...</td>
<td>...</td>
<td>
<div class="price" data-selenium="price">
<span class="currency" data-selenium="price-currency">USD</span>
<span class="crossout show-cor-tooltip">288.75</span>
<span class="sellprice">187.11</span>
</div>
</td>
</tr>
<tr>...</tr>
...
</tbody>
</table>
单击 select 框的选项字段几乎不起作用,因为它不是 PhantomJS 中的可单击 UI 元素。您必须通过 DOM 以编程方式 select 您想要的选项。例如,这可以通过将 selectElement.selectedIndex
属性 设置为正确的索引来完成。设置好后,需要在select元素上触发change事件,否则不会向服务器发送AJAX请求。
这是从我的
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);
};
更改货币设置后需要等待AJAX请求完成。这可以通过不同的方式完成:
静态等待时间 有效,但等待时间可能比请求需要的时间长:
casper.wait(5000);
等待特定的 select 或 出现效率更高,因为一旦 select 或被发现。例如,您可以等待 table 中的货币文本更改。这可以使用 XPath 轻松完成:
var x = require('casper').selectXPath; var currency = 'AED'; ... casper.waitForSelector(x("//*[@id='room-grid-table']//*[@class='currency' and contains(text(), '"+currency+"')]"));
您可以等待特定select或table中的货币的文本更改。如果更改是即时的,这将不起作用,因为 CasperJS 需要一点时间来接受更改。 20ms应该够了。
casper.waitForSelectorTextChange("#room-grid-table .currency");
等待 AJAX 响应,它通过查看所有收到的资源来工作:
casper.waitForResource("Main/GetRoomTypeDetailList").wait(50);
版本 2 的完整脚本:
var casper = require("casper").create({
verbose: true,
logLevel: 'error',
pageSettings: {
loadImages: false,
}
});
var utils = require('utils');
var x = require('casper').selectXPath;
var url = 'http://www.agoda.com/hotel-des-arts-saigon-mgallery-collection/hotel/ho-chi-minh-city-vn.html?checkin=2015-11-14&los=4&adults=2&childs=0&rooms=1';
var names = [];
var prices = [];
var currency = [];
function getName() {
var rows = document.querySelectorAll('table#room-grid-table tbody tr td:first-child .info-container .room-name span');
return Array.prototype.map.call(rows, function(e) {
return e.innerHTML;
});
}
function getPrice() {
var price = document.querySelectorAll('table#room-grid-table tbody tr td:nth-child(3) .price span.sellprice');
return Array.prototype.map.call(price, function(e) {
return e.innerHTML;
});
}
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.start(url, function() {
this.echo(this.getTitle());
});
var currency = 'AED';
casper.then(function() {
this.selectOptionByValue('select[id="currency-options"]', currency);
});
casper.waitForSelector(x("//*[@id='room-grid-table']//*[@class='currency' and contains(text(), '"+currency+"')]"));
casper.then(function() {
names = this.evaluate(getName);
prices = this.evaluate(getPrice);
});
casper.then(function() {
utils.dump(names);
utils.dump(prices);
})
casper.run();