Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ajax request in PhantomJs script

Problem: Ajax request within phantomJs script to a local page doesn't work (no response)

Question: How can I make it work? Any ideas or possible solutions?

Description: I'm running a phantomJs script and I need to access some data that is provided by a php function in another page (local). In order to do that, I use an ajax request to that page inside the phantomjs script. However, the request doesn't do anything. The script is:

page.open(url, function (status) {
    page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js', function () {
        console.log("Solve Captcha");
        $.ajax({
            url: 'captcha.php',
            data: { filename: 'C:\\wamp\\www\\images\\0.png' },
            type: 'post',
            success: function (output) {
                console.log('Solved');
                phantom.exit();
            },
        });
    });
});

The php page is in a local WAMP server and it has been tested with ajax (outside a phantomJs script), and it works fine. The script and the php files are in the folder C:\wamp\www, while the image 0.png is in the sub-folder C:\wamp\www\images.

Important: The page captcha.php is in the localhost, while phantomJs is requesting a page that is not local, that is, page.open opens a url that is not local.

I don't understand why making this request in a phantomJs script won't work. Could you please help me?

like image 971
Guilherme Salomé Avatar asked Feb 23 '15 21:02

Guilherme Salomé


1 Answers

page.includeJs() injects jQuery into the page, so it is only accessible from the page context (inside of page.evaluate()). The page context is sandboxed, so you cannot call phantom.exit() from the page context, because there is no such object window.phantom.

You have two possibilities to make it work.

Blocking AJAX

jQuery.ajax() accepts an async: false property to make a blocking AJAX call, so you can simply make the call and then continue with the execution in iterative style.

page.open(url, function (status) {
    page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js', function () {
        console.log("Solve Captcha");
        page.evaluate(function(){
            $.ajax({
                async: false, // this
                url: 'http://localhost/captcha.php',
                data: { filename: 'C:\\wamp\\www\\images\\0.png' },
                type: 'post',
                success: function (output) {
                    console.log('Solved');
                },
            });
        });
        phantom.exit();
    });
});

Wait for completion

waitFor from the examples can be used to wait for a specific condition to be set. This condition should be set in the success callback of the AJAX call:

page.open(url, function (status) {
    page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js', function () {
        console.log("Solve Captcha");
        page.evaluate(function(){
            window._finishedCall = false;
            $.ajax({
                url: 'http://localhost/captcha.php',
                data: { filename: 'C:\\wamp\\www\\images\\0.png' },
                type: 'post',
                success: function (output) {
                    console.log('Solved');
                    window._finishedCall = true;
                },
            });
        });
        waitFor(function check(){
            return page.evaluate(function(){
                return window._finishedCall;
            });
        }, function onReady(){
            phantom.exit();
        }, 10000); // 10 seconds maximum timeout
    });
});

The second problem is that you want to make a cross-domain request, because captcha.php is on localhost and url is distinct from localhost. You need to run PhantomJS with the --web-security=false option and use fully qualified URLs: http://localhost/captcha.php.

like image 150
Artjom B. Avatar answered Sep 19 '22 19:09

Artjom B.