一种解决方法是使用微软的WebBrowser控件之类模仿浏览器操作,但该控件类似于一个小浏览器,界面显示会消耗不少资源,用于数据抓取的话成本太高。PhantomJS和CasperJS这样的headless浏览器就可以解决这些问题。另一个广泛使用的工具是ThoughtWorks公司的Selenium,支持除了JavaScript之外的其它语言编写的用例脚本,在此不作赘述。
学习使用CasperJS,可能需要一些JavaScript的背景知识。本人对JavaScript只能说是略知一二,这几天在学习CasperJS时遇到不少问题。比如DOM操作时的document.querySelector方法,问题如下:
var casper = require("casper").create() var x = require('casper').selectXPath; casper.start('https://www.baidu.com'); casper.then(function() { var titleNode = document.querySelector(x('//*[@id="setf"]')); this.echo('Title is: ' + titleNode.innerHTML); }); casper.run();
这段简单代码,本意是打开百度,然后查询id为setf的HTML元素的内容。但运行时报如下错误:
C:\tmp>casperjs su.js SYNTAX_ERR: DOM Exception 12: An invalid or illegal string was specified. C:/tmp/su.js:5 D:/n1k0-casperjs-4f105a9/modules/casper.js:1553 in runStep D:/n1k0-casperjs-4f105a9/modules/casper.js:399 in checkStep
百思不得其解。测试时发现document的其它属性也无法正确获取。
最后才在CasperJS文档上看到,跟PhantomJS一样,必须用Casper对象的evaluate方法对页面的DOM对象及元素进行操作。也就是说,不能象在普通页面上的JS脚本一样,直接在CasperJS脚本中调用document对象的属性和方法。需改成如下方式:
var casper = require("casper").create() var x = require('casper').selectXPath; casper.start('https://www.baidu.com'); casper.then(function() { var titleText = this.evaluate(function() { return document.querySelector(x('//*[@id="setf"]')).innerHTML; }); this.echo('Title is: ' + titleText); }); casper.run();
官方文档中的例子明确的用evaluate方法调用document.querySelector方法。但这样修改之后,运行时又报如下错误:
C:\tmp>casperjs su.js Title is: null
取得的innerHTML值为空?
由于习惯用xpath选择器,所以上述querySelector中也使用了xpath选择器,而不是CSS选择器。但看官方文档中的querySelector中的方法使用的却是CSS选择器,难道跟这个有关系?改成CSS选择器试试:
var titleText = this.evaluate(function() { return document.querySelector('#setf').innerHTML; });
然后再运行:
C:\tmp>casperjs su.js Title is: 把百度设为主页
结果正确了。查找原因,原来querySelector是浏览器支持的JS方法,并不是CasperJS内置方法,所以只支持标准CSS选择器,而不能用CasperJS的xpath选择器。
原创文章,作者:苏葳,如需转载,请注明出处:https://www.swmemo.com/2123.html