如何将参数传递给pjscrape?

时间:2012-12-14 01:37:49

标签: javascript phantomjs

pjscrape非常适合拼抢,但是我很难弄清楚如何将参数传递给我的刮刀。

它需要配置文件的命令行参数,但我不确定我的配置函数/变量的范围是什么。

我希望每个域都有配置,包括基本URL,选择器等,并构建一个能够从此配置中读取的通用刮刀。

我该怎么做?

1 个答案:

答案 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])
        })
    });