使用Node.js和XPath对页面进行性能分析

我进入了一些网站与Node.js刮。 我想使用XPath,因为我可以用几种GUI自动生成它。 问题是,我无法find有效的方法。

  1. jsdom非常慢。 它在一分钟左右parsing500KiB文件,全部CPU负载和大量内存占用。
  2. 用于HTMLparsing的stream行库(例如cheerio )既不支持XPath,也不公开W3C兼容的DOM。
  3. 有效的HTMLparsing显然是在WebKit中实现的,所以使用phantomcasper将是一种select,但是这些parsing需要以特殊的方式运行,而不仅仅是node <script> 。 我不能依靠这种变化所暗示的风险。 例如,要find如何用phantom运行node-inspector困难多了。
  4. Spooky是一个选项,但是它有足够的bug ,所以它在我的机器上根本没有运行。

然后用XPathparsingHTML页面的正确方法是什么?

你可以通过几个步骤来完成。

  1. parse5parsingHTML。 不好的部分是结果不是DOM。 虽然速度够快,并且符合W3C标准。
  2. 使用xmlserializer将其序列parse5 XHTML,它接受parse5的类DOM结构作为input。
  3. 再次用xmldomparsingXHTML。 现在你终于有了这个DOM。
  4. xpath库build立在xmldom ,允许您xmldom XPath查询。 请注意,XHTML有它自己的命名空间,像//a这样的查询将不起作用。

最后你得到这样的东西。

 var fs = require('fs'); var xpath = require('xpath'); var parse5 = require('parse5'); var xmlser = require('xmlserializer'); var dom = require('xmldom').DOMParser; fs.readFile('./test.htm', function (err, html) { if (err) throw err; var document = parse5.parse(html.toString()); var xhtml = xmlser.serializeToString(document); var doc = new dom().parseFromString(xhtml); var select = xpath.useNamespaces({"x": "http://www.w3.org/1999/xhtml"}); var nodes = select("//x:a/@href", doc); console.log(nodes); }); 

Libxmljs是目前最快的实现( 类似于基准testing ),因为它只绑定到支持XPath 1.0查询的LibXML C库:

 var libxmljs = require("libxmljs"); var xmlDoc = libxmljs.parseXml(xml); // xpath queries var gchild = xmlDoc.get('//grandchild'); 

但是,您需要先清理HTML,然后将其转换为正确的XML。 为此,您可以使用HTMLTidy命令行实用程序( tidy -q -asxml input.html ),或者如果您希望它只保留节点,那么像xmlserializer这样的应用程序就可以做到这一点。

我刚刚开始使用npm install htmlstrip-native ,它使用本机实现来parsing和提取相关的html部分。 它声称比纯js实现快50倍(我还没有证实这一说法)。

根据您的需要,您可以直接使用html-strip,或者解除代码和绑定,使您自己在内部使用的htmlstrip-native

如果你想使用xpath,那么使用已经在这里包装的包装; https://www.npmjs.org/package/xpath

我认为渗透是你正在寻找的。

  • 使用本机libxml C绑定
  • 支持CSS 3.0和XPath 1.0select器混合
  • 嘶嘶声select器,Slickselect器,等等
  • 没有像jQuery,cheerio或jsdom这样的大型依赖关系
  • HTMLparsing器function

    • 快速parsing
    • 非常快的search
    • 小内存占用
  • HTML DOMfunction

    • 加载并searchajax内容
    • DOM交互和事件
    • 执行embedded式和远程脚本
    • 执行DOM中的代码

这是一个例子:

 osmosis.get(url) .find('//div[@class]/ul[2]/li') .then(function () { count++; }) .done(function () { assert.ok(count == 2); assert.done(); }); 

可能从来没有正确的方法来parsingHTML页面。 网上抓取和爬行的第一次审查表明, Scrapy可以成为您的需要的一个很好的候选人。 它接受CSS和XPathselect器。 在Node.js的领域,我们有一个漂亮的模块节点渗透 。 这个模块是build立在libxmljs之上的,所以它应该支持CSS和XPath,尽pipe我没有find任何使用XPath的例子。