pjscrape非常适合抓取,但是我很难弄清楚如何将参数传递给我的抓取器。
它需要配置文件的命令行参数,但我不确定我的配置函数/变量的范围是什么。
我希望每个域都有配置,包括基本 URL、选择器等,并构建一个能够从该配置中读取的通用爬虫。
我怎样才能做到这一点?
pjscrape非常适合抓取,但是我很难弄清楚如何将参数传递给我的抓取器。
它需要配置文件的命令行参数,但我不确定我的配置函数/变量的范围是什么。
我希望每个域都有配置,包括基本 URL、选择器等,并构建一个能够从该配置中读取的通用爬虫。
我怎样才能做到这一点?
Pjscrape 会将所有参数评估为全局范围内的配置文件,您可以传入任意数量的配置文件。因此,在一个或多个文件中配置每个域的抓取工具应该很简单。例如:
base_config.js
var myConfigs = [];
my_site.js
myConfigs.push({
title: 'My Site',
url: 'http://www.example.com',
scraper: 'div#my-site-info'
});
刮刀.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 中。基本上有两种方法可以解决这个问题:
始终处理不需要访问外部范围的函数。所以每个站点配置文件都会指定完整的爬虫函数,而不仅仅是可插入的变量。
使用 创建刮板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])
})
});