baudehlo / node-phantom-simple

Simple bridge to phantomjs for Node
MIT License
201 stars 70 forks source link

page.evaluate cloud not get any result #153

Open willin opened 7 years ago

willin commented 7 years ago
const driver = require('node-phantom-simple');
const phantom = require('phantomjs-prebuilt');

driver.create({
  path: phantom.path
}, (err, browser) => {
  browser.createPage((err2, page) => {
    page.open('https://www.google.com/', (err3, status) => {
      console.log('opened site? ', status);
      page.evaluate(() => document.getElementsByTagName('body')[0].innerHTML, (err4, result) => {
        console.log(result);
        browser.exit();
      });
    });
  });
});
opened site?  success
null

if i use:

page.get('content', function (err, html) {
  console.log("Page HTML is: " + html);
});

can print html result.

using basic example:

const driver = require('node-phantom-simple');

driver.create({ path: require('phantomjs-prebuilt').path }, (err, browser) => browser.createPage((err, page) => page.open('http://tilomitra.com/repository/screenscrape/ajax.html', (err, status) => {
  console.log('opened site? ', status);
  page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js', (err) => {
    // jQuery Loaded.
    // Wait for a bit for AJAX content to load on the page. Here, we are waiting 5 seconds.
    setTimeout(() => page.evaluate(() => {
      // Get what you want from the page using jQuery. A good way is to populate an object with all the jQuery commands that you need and then return the object.
      let h2Arr = [],
        pArr = [];

      $('h2').each(function () { h2Arr.push($(this).html()); });
      $('p').each(function () { pArr.push($(this).html()); });

      return {
        h2: h2Arr,
        p: pArr
      };
    }, (err, result) => {
      console.log(result);
      browser.exit();
    }), 5000);
  });
})));
// opened site?  success
// null
Reewr commented 7 years ago

PhantomJS does not support ES6 syntax. In the examples above, you use () => when sending functions to page.evaluate. Functions sent to page.evaluate must conform to ES5 syntax. Try replacing () => with function()

willin commented 7 years ago
page.evaluate(function () {
  return [1, 2, 3].map(x => x + 1);
})

yes, i tried this get null but in browser:

wx20170807-232502 2x
wx20170807-233602 2x
page.evaluate(function () {
        return [].slice.call(document.querySelectorAll('tr')).slice(5, document.querySelectorAll('tr').length - 3);
      }, (err4, result) => {
        console.log(result);
        browser.exit();
      });
opened site?  success
[]
Reewr commented 7 years ago
page.evaluate(function () {
  return [1, 2, 3].map(x => x + 1);
})

This will not work in PhantomJS as you are using ES6 syntax. Arrow functions () => {} were introduced in ES6, which PhantomJS does not support.

The correct syntax would be:

page.evaluate(function () {
  return [1, 2, 3].map(function(x) { return x + 1});
});

The other example of yours, with tr elements will most likely not work either, since you're returning a list of DOM Elements that cannot be turned into strings.

Keep this in mind when using page.evalulate:

The function you are sending into the function will be turned into a string and then executed with eval or new Function. This means that it will not have access to anything outside of the scope of itself (and the browser scope, so objects like document and window are available). The values it takes as arguments as well as return values has to be JSONinifable.