如何通过 CasperJS 从具有特定 class 的元素中获取 href?
How to get hrefs from from elements with a certain class through CasperJS?
我有一个包含以下格式信息的网页:
<p>
<a class="class1" href="href1">text1</a>
text2
</p>
<p>
<a class="class1" href="href2">text1a</a>
text2a
</p>
使用 CasperJS,我需要获取包含在具有 class1 的元素中的所有信息的数组,格式如下:
href1
text1
text2
href2
text1a
text2a
我试过使用此代码:
var casper = require('casper').create();
casper.start('url', function() {
require('utils').dump(this.getElementsAttribute('div[class="class1"]',
'class'));
});
casper.run();
但是,我只得到了一个“[]”作为答案。
谁能帮我找出代码中的错误?
div[class="class1"]
作为选择器无法工作,因为您的标记中没有任何具有 class1
class 的 <div>
元素。您可以尝试以下方法,但不会让您走得太远:
this.getElementsAttribute('a.class1', 'href');
在页面上下文中构建对象数组
仅使用 CasperJS 函数执行此操作很难并且可能容易出错。通过遍历所有 link 并获取您需要的部分,可以更容易地做到这一点。
casper.then(function(){
var info = this.evaluate(function(){
var links = document.querySelectorAll(".class1");
// iterate over links and collect stuff
return Array.prototype.map.call(links, function(link){
return {
href: link.href,
hrefText: link.textContent.trim(),
afterText: link.parentNode.childNodes[2].textContent.trim()
};
});
});
require('utils').dump(info);
});
这是如何工作的:
您可以通过查询所有带有 class1
的所有元素来获取所有 link。由于querySelectorAll()
的结果不是一个数组,而是一个类似数组的NodeList,所以不能直接在上面使用.map()
。
每个 link 都有一个 href
属性 和一个 textContent
属性。 link 之后的文字有点棘手。您首先需要获取 link (<p>
) 的父节点,然后尝试通过访问 childNodes
属性 来获取 link 之后的 TextNode。 =32=]
可能必须使用
childNodes[2]
而不是 childNodes[1]
,因为第一个 (childNodes[0]
) 可能是一个包含空格的 TextNode,因此它之后的所有内容都会移动。
在页面上下文中构建单个字符串
您也可以遍历它以获取文本表示形式:
casper.then(function(){
var info = this.evaluate(function(){
var links = document.querySelectorAll(".class1");
// iterate over links and collect stuff
return Array.prototype.map.call(links, function(link){
return [
link.href,
link.textContent.trim(),
link.parentNode.childNodes[2].textContent.trim()
].join('\n');
}).join('\n\n');
});
this.echo(info);
});
工作原理:
JavaScript 数组有一个 join()
function。它可以使用指定的分隔符连接每个元素。
请记住,页面上下文 (evaluate()
) 是沙盒化的。 documentation 表示:
Note: The arguments and the return value to the evaluate
function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.
Closures, functions, DOM nodes, etc. will not work!
我有一个包含以下格式信息的网页:
<p>
<a class="class1" href="href1">text1</a>
text2
</p>
<p>
<a class="class1" href="href2">text1a</a>
text2a
</p>
使用 CasperJS,我需要获取包含在具有 class1 的元素中的所有信息的数组,格式如下:
href1
text1
text2
href2
text1a
text2a
我试过使用此代码:
var casper = require('casper').create();
casper.start('url', function() {
require('utils').dump(this.getElementsAttribute('div[class="class1"]',
'class'));
});
casper.run();
但是,我只得到了一个“[]”作为答案。
谁能帮我找出代码中的错误?
div[class="class1"]
作为选择器无法工作,因为您的标记中没有任何具有 class1
class 的 <div>
元素。您可以尝试以下方法,但不会让您走得太远:
this.getElementsAttribute('a.class1', 'href');
在页面上下文中构建对象数组
仅使用 CasperJS 函数执行此操作很难并且可能容易出错。通过遍历所有 link 并获取您需要的部分,可以更容易地做到这一点。
casper.then(function(){
var info = this.evaluate(function(){
var links = document.querySelectorAll(".class1");
// iterate over links and collect stuff
return Array.prototype.map.call(links, function(link){
return {
href: link.href,
hrefText: link.textContent.trim(),
afterText: link.parentNode.childNodes[2].textContent.trim()
};
});
});
require('utils').dump(info);
});
这是如何工作的:
您可以通过查询所有带有 class1
的所有元素来获取所有 link。由于querySelectorAll()
的结果不是一个数组,而是一个类似数组的NodeList,所以不能直接在上面使用.map()
。
每个 link 都有一个 href
属性 和一个 textContent
属性。 link 之后的文字有点棘手。您首先需要获取 link (<p>
) 的父节点,然后尝试通过访问 childNodes
属性 来获取 link 之后的 TextNode。 =32=]
可能必须使用
childNodes[2]
而不是 childNodes[1]
,因为第一个 (childNodes[0]
) 可能是一个包含空格的 TextNode,因此它之后的所有内容都会移动。
在页面上下文中构建单个字符串
您也可以遍历它以获取文本表示形式:
casper.then(function(){
var info = this.evaluate(function(){
var links = document.querySelectorAll(".class1");
// iterate over links and collect stuff
return Array.prototype.map.call(links, function(link){
return [
link.href,
link.textContent.trim(),
link.parentNode.childNodes[2].textContent.trim()
].join('\n');
}).join('\n\n');
});
this.echo(info);
});
工作原理:
JavaScript 数组有一个 join()
function。它可以使用指定的分隔符连接每个元素。
请记住,页面上下文 (evaluate()
) 是沙盒化的。 documentation 表示:
Note: The arguments and the return value to the
evaluate
function must be a simple primitive object. The rule of thumb: if it can be serialized via JSON, then it is fine.Closures, functions, DOM nodes, etc. will not work!