pjscrape非常适合拼抢,但是我很难弄清楚如何将参数传递给我的刮刀。
它需要配置文件的命令行参数,但我不确定我的配置函数/变量的范围是什么。
我希望每个域都有配置,包括基本URL,选择器等,并构建一个能够从此配置中读取的通用刮刀。
我该怎么做?
答案 0 :(得分:4)
Pjscrape会将所有参数作为全局范围内的配置文件进行评估,您可以根据需要传入任意数量的配置文件。因此,在一个或多个文件中配置每个域的scraper应该很简单。例如:
<强> base_config.js 强>
var myConfigs = [];
<强> my_site.js 强>
myConfigs.push({
title: 'My Site',
url: 'http://www.example.com',
scraper: 'div#my-site-info'
});
<强> scraper.js 强>
myConfigs.forEach(function(config) {
pjs.addSuite({
title: config.title,
url: config.url,
scraper: config.scraper
})
});
然后调用:
~> phantomjs /path/to/pjscrape.js base_config.js my_site.js <...> scraper.js
这里棘手的部分是你想要使用刮刀功能,而不仅仅是选择器。 PhantomJS在“沙盒”环境中运行刮刀,不可以访问全局范围变量。所以这将不工作:
myConfigs.forEach(function(config) {
pjs.addSuite({
scraper: function() {
// will fail - config is undefined!
return $(config.selector).text();
}
})
});
这是一个微不足道的例子,但你明白了。 PhantomJS现在支持将参数传递给page.evaluate
,但这些还没有构建到Pjscrape中。基本上有两种方法可以解决这个问题:
始终处理不需要访问外部作用域的函数。因此,每个站点配置文件都将指定完整的scraper函数,而不仅仅是可插入的变量。
使用new Function("...")
创建您的抓取工具,在创建字符串时传入变量。这就是Pjscrape在引擎盖下的表现,但是公平的警告 - 除了最直接的案例外,它可以迅速变得丑陋。我在这里使用的一种方法是使用Function#toString
并传入参数。这可能如下所示:
function makeFunc(f, args) {
return new Function('return (' + f.toString() + ')' +
'.apply(null, ' + JSON.stringify(args) + ');');
}
myConfigs.forEach(function(config) {
pjs.addSuite({
scraper: makeFunc(function(selector) {
// works - config.selector is passed in as the "selector" arg
return $(selector).text();
}, [config.selector])
})
});