2

pjscrape非常适合抓取,但是我很难弄清楚如何将参数传递给我的抓取器。

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

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

我怎样才能做到这一点?

4

1 回答 1

4

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])
        })
    });
    
于 2012-12-17T02:08:53.853 回答