2016-08-04 11 views
0

25のエントリのリストを含むページが含まれているWebサイトがあります。各エントリは、必要な情報を含むページへのリンクです。 1)最初のエントリへのリンクをクリック 2)すべてのhtmlを取得 3)リスティングページに戻る(このボタンがあります) 4)お互いに繰り返しナイトメアと一緒に移動するとページ間を移動して掻き集める

私はこれを可能な限り効率的に行いたいと約束しました。ここでは動作しないコードスケッチがあります:

var Nightmare = require('nightmare'); 
var nightmare = Nightmare({ openDevTools: true, show: true }) 
var Xray = require('x-ray'); 
var x = Xray(); 
var resultArr = []; 

nightmare 
.goto(hidTestURL) 
.wait(2500) 
.click('input[name="propertySearchOptions:advanced"]') //start navigating to listing page 
.wait(2500) 
.type('input[name="propertySearchOptions:streetName"]', 'Main') 
.wait(2500) 
.select('select[name="propertySearchOptions:recordsPerPage"]', '25') 
.wait(2500) 
.click('input[name="propertySearchOptions:search"]') //at listing page 
.wait(2500) 
.then(function(){ 
    nightmare 
    .click('a[href^="Property.aspx?prop_id=228645"]') //first entry 
    .evaluate(function(){ //retrieve info 
    var resultArr = []; 
    resultArr.push(document.querySelector('html').innerHTML); 
    }) 
}) 

nightmare 
.click('a[id="propertyHeading_searchResults"]') //return to listing page 
.evaluate(function(){ 
    return resultArr.push(document.querySelector('html').innerHTML); retrieve listing page info to show that it returned. 
}) 
.then(function (resultArr) { 
    console.log('resultArr', resultArr); 
    x(resultArr[1], '[email protected]') //output listing page html 
    .write('results.json'); 
}) 

これはリスティングページまで取得され、これ以上進まません。私も同じコードを試しましたが、nightmareのすべての使用のためにreturn nightmareと最初のものを除いて。私はreturnを使ったいくつかの例を見ていましたが、これを実行したときにコードがエラーを投げました。

また、第3のnightmare(空白スペースの後ろ)は含まず、代わりに.click()にまっすぐ進むことによって古い悪夢のインスタンスを続行しようとしましたが、これもエラーを投げかけました。

悪夢の構文とセマンティクスについてはっきりと助けが必要ですが、APIリストのほかにオンラインのドキュメントはあまりありません。どのように私はこの仕事をすることができます誰も知っていますか?

答えて

5

最初に、2つのチェーンに分かれているようなナイトメアを呼び出すととなるでしょう。おそらくはあなたが望むことをするつもりはありません。メモリーサービス、2番目のチェーンからのアクションは、最初のものの直後にキューに入れられ、(おそらく)望ましくない動作を引き起こします。あなたはそれが少し違って書かれていたと言いました - 私はそれを見て好奇心が強いでしょう、少し近いかもしれないように聞こえます。

第2に、resultArr.evaluate()に持ち上げようとしていますが、これはできません。 .evaluate()に渡された関数は、文字列化され、Electronの内部で再構成されます。つまり、関数の周囲のコンテキストを失うことになります。あなたが好奇心が強いならば、nightmare-examplesThis exampleはもう少し深く入ります。

第三に、そしておそらくこれは意図を誤解タイプミスか、私です:あなたhrefセレクタが開始-と(^=)演算子を使用して、意図的ということでしょうか?それが末尾にあるべきか($=)?

第4、looping over asynchronous operations is tricky。私はまた、つまずくブロックかもしれない印象を得ますか?

これを念頭に置いて、元のスクリプトを修正してみましょう。

var Nightmare = require('nightmare'); 
var nightmare = Nightmare({ openDevTools: true, show: true }) 
var Xray = require('x-ray'); 
var x = Xray(); 

nightmare 
.goto(hidTestURL) 
.wait(2500) 
.click('input[name="propertySearchOptions:advanced"]') //start navigating to listing page 
.wait(2500) 
.type('input[name="propertySearchOptions:streetName"]', 'Main') 
.wait(2500) 
.select('select[name="propertySearchOptions:recordsPerPage"]', '25') 
.wait(2500) 
.click('input[name="propertySearchOptions:search"]') //at listing page 
.wait(2500) 
.evaluate(function(){ 
    //using `Array.from` as the DOMList is not an array, but an array-like, sort of like `arguments` 
    //planning on using `Array.map()` in a moment 
    return Array.from(
    //give me all of the elements where the href contains 'Property.aspx' 
    document.querySelectorAll('a[href*="Property.aspx"]')) 
    //pull the target hrefs for those anchors 
    .map(a => a.href); 
}) 
.then(function(hrefs){ 
    //here, there are two options: 
    // 1. you could navigate to each link, get the information you need, then navigate back, or 
    // 2. you could navigate straight to each link and get the information you need. 
    //I'm going to go with #1 as that's how it was in your original script. 

    //here, we're going to use the vanilla JS way of executing a series of promises in a sequence. 
    //for every href in hrefs, 
    return hrefs.reduce(function(accumulator, href){ 
    //return the accumulated promise results, followed by... 
    return accumulator.then(function(results){ 
     return nightmare 
     //click on the href 
     .click('a[href="'+href+'"]') 
     //get the html 
     .evaluate(function(){ 
      return document.querySelector('html').innerHTML; 
     }) 
     //add the result to the results 
     .then(function(html){ 
      results.push(html); 
      return results; 
     }) 
     .then(function(results){ 
      //click on the search result link to go back to the search result page 
      return nightmare 
      .click('a[id="propertyHeading_searchResults"]') 
      .then(function() { 
       //make sure the results are returned 
       return results; 
      }); 
     }) 
    }); 
    }, Promise.resolve([])) //kick off the reduce with a promise that resolves an empty array 
}) 
.then(function (resultArr) { 
    //if I haven't made a mistake above with the `Array.reduce`, `resultArr` should now contain all of your links' results 
    console.log('resultArr', resultArr); 
    x(resultArr[1], '[email protected]') //output listing page html 
    .write('results.json'); 
}); 

がうまくいけば、それはあなたが始めるには十分だ:私はあなたのテストのURLへのアクセスを持っていないので、これはヒップからのビットであるとして、確かにテストされていません。

関連する問題