如何在NodeJS中按值获取元素的CSS选择器?

时间:2017-01-25 14:40:55

标签: javascript node.js dom css-selectors cheerio

我正在编写一个使用Node的Web抓取工具,并考虑使用像Cheerio或JSDom这样的模块将HTML解析为DOM以获取一组URL。但是,我有一个必要的特定功能。

我的目标是构建一个可以在网站上抓取多个类似页面的刮刀,以获取一些关键信息。但是,我有一些包含这些信息的示例数据,我想使用它们为这些页面动态构建模型,然后使用该模型抓取其余部分。

澄清一下,如果网站上有三个页面,每个页面都包含不同的产品:

第1页:

<html>
<body>
<h1>Product 1</h1>
<p>Desc</p>
<small>$2.05</small>
</body>
</html>

第2页:

<html>
<body>
<h1>Product 2</h1>
<p>Desc</p>
<small>$8.05</small>
</body>
</html>

第3页:

<html>
<body>
<h1>Product 3</h1>
<p>Desc</p>
<small>$5.07</small>
</body>
</html>

说我已经拥有第一个产品的数据(我知道产品名称,描述和价格)。我想使用第一页获取每个元素的选择器,然后使用这些选择器从其他页面中获取数据。

鉴于DOM中标记的内容,我如何获得该元素的CSS选择器?例如:

<html>
  <body>
    <h1>Hello world</h1>
  </body>
</html>

如何为Cheerio / JSDom提供类似&#34; Hello world&#34;的字符串。并让它返回元素所在的DOM中的CSS Selector?

有没有一种简单的方法可以做到这一点(包括使用另一个框架),或者只是循环遍历整个DOM对象并单独检查每个元素的值?

1 个答案:

答案 0 :(得分:0)

使用SAX模型完成此操作最简单,最有效,但可以应用于DOM遍历。

var match, path = [];

parser.on('start', function(tag) { currentPath.push(tag); });
parser.on('end', function(tag) { currentPath.pop(); });

parser.on('text', function(text) {
  if (!match && text === 'Hello world') {
    match = path.join('/');
  }
});

如果你还需要构建DOM,你可以使用XPath来查找节点(内部只循环整个DOM),然后循环父节点。

var path = [];
var node = document.xpath('//*[.="Hello world"]')[0];

do { 
  path.push(node.tag);
} while (node = node.parent);

var match = path.reverse().join('/');

第二种方法效率低得多,特别是如果要查找许多不同的节点。 SAX方法可以一次性覆盖所有这些方法,但可能会因格式错误的输入而受到影响,具体取决于解析器的实现。

对于CSS选择器,请将'/'替换为' > '