2017-06-16 16 views
6

मैं एक nightmare.js स्क्रिप्ट जहां जहां मैं एक पृष्ठ पर कई घटक के एक स्क्रीनशॉट लेने के लिए कोशिश कर रहा हूँ चल रहा हूँ।Nightmare.js स्क्रीनशॉट बफर लंबाई 0

पहले तत्व ठीक से कब्जा कर लिया गया है, लेकिन गुना के नीचे मौजूद हर दूसरे तत्व को शून्य लंबाई के साथ पकड़ा जाता है। मैं इस मुद्दे को डीबग करने के लिए संघर्ष कर रहा हूं। किसी भी मदद की सराहना की जाएगी।

असल में यह स्क्रिप्ट एक पृष्ठ के माध्यम से चलता है और सभी चयनकर्ता से मेल खाने वाले पृष्ठ पर मौजूद तत्वों का चयन करता है। फिर, async का उपयोग करके यह प्रतिक्रिया एकत्र करता है और वस्तुओं का एक बफर देता है। मुद्दा यह है कि गुना के नीचे वाले तत्वों को स्क्रीनशॉट नहीं किया जाता है (बफर लंबाई शून्य पर समाप्त होती है)। मैंने wait() पर कोशिश की और तत्व पर स्क्रॉल किया, लेकिन मुझे अभी तक कोई सफलता नहीं मिली है।

import * as Nightmare from 'nightmare' 
import * as vo from 'vo' 
import * as async from 'async' 
import * as fs from 'fs' 

const urls:String[] = [ 
    'https://yahoo.com/' 
] 


Nightmare.action('snap', function(selector:String, done:Function) { 
    const self = this; 

    this.evaluate_now(function (selector) { 
    return Array.from(document.querySelectorAll(selector)) 
    .map((ele:Element) => { 
     if (ele) { 
     const rect = ele.getBoundingClientRect() 
     const r:Function = Math.round 
     return { 
      x: r(rect.left), 
      y: r(rect.top), 
      width: r(rect.width), 
      height: r(rect.height) 
     } 
     } 
    }) 
    }, function(err, clips) { 
    if (err) return done(err) 
    if (!clips) return done(new Error(`Selector not found`)) 
    let snaps = [] 
    const snap = (clip, cb) => { 
     self 
     .scrollTo(clip.y - clip.height, clip.x) 
     .screenshot(clip, cb) 
     .run() 
    } 
    async.mapSeries(clips.reverse(), snap, (err, res) => { 
     done(err, res) 
    }) 
    }, selector) 
}) 

const scrape = (url) => { 
    const nightmare = Nightmare({ 
    show: true 
    }); 
    nightmare 
    .goto(url) 
    .snap('.navbar') 
    .end() 
    .then((buffers:Buffer[]) => { 
     buffers.forEach((data, index) => { 
     fs.writeFileSync(`images/navbar-${index}.png`, data) 
     }) 
    }) 
} 

urls.forEach(scrape) 
+0

मैं इस मुद्दे को पुन: उत्पन्न करने की कोशिश कर रहा हूं लेकिन मुझे पता चला कि yahoo.com पृष्ठ पर ऐसा कोई तत्व ".navbar" नहीं है। क्या आप इसे स्पष्ट कर सकते हैं? –

+0

Evgeny, निश्चित रूप से। इसे बूटस्ट्रैप वाले पेज पर आज़माएं, यानी: https://getbootstrap.com/ – auser

+0

क्या आप इसे दोहराने में सक्षम थे, @EvgenySorokin? – auser

उत्तर

1

अलग प्रवाह से यह कोशिश कर रहा है, बेहतर परिणाम दे दी तत्व करने के लिए पहली पुस्तक और फिर अपनी सीमाएं लें और फिर स्क्रीनशॉट के लिए आगे बढ़ें।

const Nightmare = require('nightmare'); 
const fs = require('fs'); 
const nightmare = Nightmare({ 
    show: true, 
    openDevTools: false, 
    gotoTimeout: 45000 
}); 

nightmare.goto('https://www.google.co.in/?#safe=off&q=nightmare') 
    .wait(1000) 
    .evaluate(getElements, 'div.g') 
    .then(() => { 
    console.log("Calling screenshots: "); 
    getAllScreenshots(0); 
    }) 
    .catch(function(err) { 
    console.log(err); 
    }); 

function getAllScreenshots(index) { 
    console.log("Called with index: ", index) 
    nightmare.evaluate(function(index) { 
     const r = Math.round; 
     if(index >= window.__nightmare.output.length) { 
     return false; 
     } 
     var element = window.__nightmare.output[index]; 
     console.log(index, element.innerHTML); 
     element.scrollIntoView(false); 
     var bound = element.getBoundingClientRect(); 
     return { 
     x: r(bound.left)-10, 
     y: r(bound.top)-10, 
     width: r(element.clientWidth)+40, 
     height: r(element.clientHeight)+10 
     } 
    }, index) 
    .then(function(bound) { 
     if(!bound) { 
     return; 
     } 
     console.log("Taking screenshot: ", bound); 
     nightmare.wait(500).screenshot(__dirname + '/images/navbar' + index + '.png', bound) 
     .then(function() { 
      console.log("Calling Next of: ", index); 
      getAllScreenshots(index + 1); 
     }).catch(function(err) { 
      console.log(err); 
     }) 
    }) 
    .catch(function(err) { 
     console.log(err); 
    }); 
} 

function getElements(selector) { 
    var elements = document.querySelectorAll(selector); 
    window.__nightmare.output = elements; 
    console.log(elements.length); 
} 
+0

यह बहुत अच्छा है। धन्यवाद! – auser

4

दरअसल, स्क्रीनशॉट() फ़ंक्शन दृश्यमान स्क्रीन से निर्देशांक लेता है।
उदाहरण के लिए, अगर किसी भी तत्व के (एक्स, वाई) तो आप स्क्रॉल कर सकते हैं है (10, 1000) और अपने विंडो का आकार है (800,600) (900: element.y, 0) और फिर कम से स्क्रीनशॉट लेने (element.y- scroll.y = 100, element.x)

मैं अंत में कोड काम कर रहे है: दृष्टिकोण में अंतर है::

const Nightmare = require('nightmare'); 
const fs = require('fs'); 
const nightmare = Nightmare({ 
    show: true, 
    openDevTools: true, 
}); 

nightmare.goto('https://in.news.yahoo.com/') 
    .wait(1000) 
    .evaluate(getBounds, '.Cf') 
    .then(function(rects) { 
    console.log(rects); 

    function getScreenshot(rects, index) { 
     if (index == rects.length) return; 
     nightmare.scrollTo(rects[index].y, 0) 
     .screenshot(__dirname + '/images/navbar' + index + '.png', { 
      //60 is height of the top element which remains 
      x: rects[index].x-10, 
      y: 60, 
      width: rects[index].width+30, 
      height: rects[index].height +60 
     }) 
     .then(function() { 
      console.log("Calling next. " + index); 
      getScreenshot(rects, index + 1); 
     }).catch(function(err) { 
      console.log(err); 
     }) 
    }; 

    getScreenshot(rects, 0); 
    }) 
    .catch(function(err) { 
    console.log(err); 
    }); 

function getBounds(selector) { 
    var elements = document.querySelectorAll(selector); 
    if (elements && elements.length > 0) { 
    var arr = []; 
    const r = Math.round; 
    for (var ii = 0; ii < elements.length; ii++) { 
     var rect = elements[ii].getBoundingClientRect(); 
     arr.push({ 
     x: r(rect.left), 
     y: r(rect.top), 
     width: r(rect.width), 
     height: r(rect.height) 
     }) 
    } 
    console.log("Elements found: ", arr.length); 
    return arr; 
    } 
    return null; 
} 
संबंधित मुद्दे