4

ヘッドレス ブラウジング用の SpookyJS、CasperJS、および PhantomJS ツールチェーンを使用して Web サイトをクロールするために、小さな Lambda 関数をまとめました。タスクは非常に単純で、数か月前のある時点で Lambda で動作していました。私は最近、いくつかのことを変更する必要があり、プロジェクトにもう一度取り組みたいと思っていましたが、新たに始めて、Lambda をエラーなしで実行するのに苦労しました。私の質問は、どのように Lambda で phantomjs を実行できますか?

私が実行しているコード例は次のとおりです。

spooky.start('http://en.wikipedia.org/wiki/Spooky_the_Tuff_Little_Ghost');
spooky.then(function () {
    this.emit('hello', 'Hello, from ' + this.evaluate(function () {
        return document.title;
    }));
});
spooky.run();

Lambda で発生しているエラーは次のとおりです。

{ [Error: Child terminated with non-zero exit code 1] details: { code: 1, signal: null } }

すべてが Lambda で実行できることを確認するために、さまざまな手順に従いました。以下は、私が診断しようとしたものの長いリストです。

  1. を使用してローカルで実行しnode index.js、動作していることを確認します
  2. npm インストール呼び出しで推奨され、ここで説明されているように、package.json と js ファイルをコンパイルのために Amazon Linux EC2 インスタンスにアップロードします。
  3. npm installec2 インスタンスで実行し、再度実行node index.jsして正しい出力を確認します
  4. すべてを圧縮し、cli を使用して AWS にデプロイします

私のpackage.jsonは次のとおりです。

{
  "name": "lambda-spooky-test",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "casperjs": "^1.1.3",
    "phantomjs-prebuilt": "^2.1.10",
    "spooky": "^0.2.5"
  }
}

また、次のことも試みました (ほとんどはローカルおよび AWS EC2 インスタンスでも動作しますが、Lambda でも同じエラーが発生します:

  1. ビルド済みでないファントムのバージョンを試す
  2. パスからcasperjsとphantomjsにアクセスできるようにしますprocess.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'] + ':' + process.env['LAMBDA_TASK_ROOT'] + '/node_modules/.bin'; console.log( 'PATH: ' + process.env.PATH );
  3. child_process の.spawn()呼び出しをラップして spawn 呼び出しを検査すると、次の結果が得られました。

    { '0': 'casperjs',
      '1': 
       [ '/var/task/node_modules/spooky/lib/bootstrap.js',
         '--transport=http',
         '--command=casperjs',
         '--port=8081',
         '--spooky_lib=/var/task/node_modules/spooky/lib/../',
         '--spawnOptions=[object Object]' ],
      '2': {} }
    
  4. 直接呼び出し.exec('casperjs')て、.exec('phantomjs --version')ローカルおよび EC2 で動作することを確認しますが、Lambda で次のエラーが発生します。コマンド:

    `require('child_process').exec('casperjs', (error, stdout, stderr) => {
    if (error) { console.error('error: ' + error); }
       console.log('out: ' + stdout);
       console.log('err: ' + stderr);
    });
    

両方で次の結果が得られます。

err: Error: Command failed: /bin/sh -c casperjs
module.js:327
    throw err;
    ^

Error: Cannot find module '/var/task/node_modules/lib/phantomjs'
    at Function.Module._resolveFilename (module.js:325:15)
    at Function.Module._load (module.js:276:25)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/var/task/node_modules/.bin/phantomjs:16:15)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)

2016-08-07T15:36:37.349Z    b9a1b509-5cb4-11e6-ae82-256a0a2817b9    sout: 
2016-08-07T15:36:37.349Z    b9a1b509-5cb4-11e6-ae82-256a0a2817b9    serr: module.js:327
    throw err;
    ^

Error: Cannot find module '/var/task/node_modules/lib/phantomjs'
    at Function.Module._resolveFilename (module.js:325:15)
    at Function.Module._load (module.js:276:25)
    at Module.require (module.js:353:17)
    at require (internal/module.js:12:17)
    at Object.<anonymous> (/var/task/node_modules/.bin/phantomjs:16:15)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)
    at Function.Module.runMain (module.js:441:10)
4

1 に答える 1

3

問題は、パスに を含めることnode_modules/.binで、ローカル マシンと ec2 マシンの両方で機能することであることがわかりました。これは、これらのファイル/binがそれぞれのライブラリのアクション フォルダーを指しているだけだからです。これらのファイル内の呼び出しが相対パスを使用する場合、これは壊れます。問題:

[ec2-user@ip-172-31-32-87 .bin]$ ls -lrt
total 0
lrwxrwxrwx 1 ec2-user ec2-user 35 Aug  7 00:52 phantomjs -> ../phantomjs-prebuilt/bin/phantomjs
lrwxrwxrwx 1 ec2-user ec2-user 24 Aug  7 00:52 casperjs -> ../casperjs/bin/casperjs

これを回避するには、各ライブラリのそれぞれのビンを Lambda ハンドラー関数のラムダ パスに追加します。

process.env['PATH'] = process.env['PATH'] + ':' + process.env['LAMBDA_TASK_ROOT'] 
        + ':' + process.env['LAMBDA_TASK_ROOT'] + '/node_modules/phantomjs-prebuilt/bin'
        + ':' + process.env['LAMBDA_TASK_ROOT'] + '/node_modules/casperjs/bin';

これにより、ラムダでファントム、キャスパー、スプーキーが正しく実行されるようになりました。

于 2016-08-07T16:20:45.307 に答える