javascript 在 PhantomJS 上我不能包含 jQuery,没有 jQuery 我不能发布表单数据

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/15847123/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-27 02:18:31  来源:igfitidea点击:

On PhantomJS I can't include jQuery and without jQuery I can't post form data

javascriptphantomjsevaluate

提问by newway

I am having trouble running jQuery in PhantomJS. I have found thisanswer, which talks about no variable is available inside evaluate function but the question is about a node module and on my example I only call console.loginside evaluate function. I have put this question on GitHub too.

我在 PhantomJS 中运行 jQuery 时遇到问题。我找到了这个答案,它谈到在评估函数中没有可用的变量,但问题是关于节点模块,在我的示例中,我只console.log在评估函数内部调用。我也把这个问题放在了GitHub 上

Previously, for some pages, the following evaluatecode didn't execute. Now that @b1f56gd4 has provided some help, it now prints messages; I can't execute it but now I can see this:

以前,对于某些页面,以下evaluate代码未执行。现在@b1f56gd4 提供了一些帮助,它现在打印消息;我无法执行它,但现在我可以看到:

The page at https://login.yahoo.com/ran insecure content from http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js.

https://login.yahoo.com/上的页面运行来自http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js 的不安全内容。

I can't load jQuery from different domain and the --local-to-remote-url-access=trueor --web-security=falseoptions make no difference.

我无法从不同的域加载 jQuery,并且--local-to-remote-url-access=trueor--web-security=false选项没有区别。

I will try load jQuery locally. Here is the code:

我将尝试在本地加载 jQuery。这是代码:

console.log('Loading a web page');
var url = 'https://login.yahoo.com/'; 
var page = require('webpage').create();
console.log('Setting error handling');
page.onConsoleMessage = function (msg) {
    console.log(msg);
};
page.onError = function (msg, trace) {
    console.log(msg);
    trace.forEach(function(item) {
        console.log('  ', item.file, ':', item.line);
    })
    phantom.exit();
}
console.log('Error handling is set');
console.log('Opening page');
page.open(url, function (status) {
    if (status != 'success') {
        console.log('F-' + status);
    } else {
        console.log('S-' + status); 
        //-------------------------------------------------     
        var jsLoc = '';
        jsLoc = 'jquery.min.js'; // to load local
        //jsLoc = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; // to load remote
        var func = function(pg){
            console.log('Function called');
            console.log('Page evaluating');
            console.log(pg);
            pg.evaluate(function() {
                console.log('Page evaluate started');               
                //---
                var loginVar = '[email protected]';
                var pwdVar = 'itsmypass_445f4hd564hd56f46s'; 
                //---
                $("#login_form #username").value = loginVar;
                $("#login_form #passwd").value = pwdVar;
                //---
            });
            console.log('Rendering');
            pg.render('ystsA.png');
            console.log('Rendered');
        }
        if (typeof jQuery == 'undefined') {  
            console.log('JQuery Loading');  // <<<<==== Execute only until here
            console.log('Source:['+jsLoc+']');
            var rs = page.includeJs(jsLoc, function()  // <<<<===== Fail here, jsLoc was changed to load locally and after tried remotely, i tried use page.injectJs but fail too
            { 
                console.log('JQuery Loaded');  // <<<< ===== Never reach here, no matter if loading local or remote script in include above
                func(page); 
            });
            page.render('ystsB.png');
        } else {
            console.log('JQuery Already Loaded');
            func(page);
            page.render('ystsC.png');
        }
        //-------------------------------------------------
    }
    phantom.exit();
});

After reading @g4d564w56 answer i did all without JQuery then i can fill textbox but cant click on button to post on login form.
See the new code:

在阅读@g4d564w56 的回答后,我没有使用 JQuery 完成所有操作,然后我可以填充文本框,但无法单击按钮在登录表单上发布。
查看新代码:

console.log('Loading a web page');
var url = 'https://login.yahoo.com/'; 
var page = require('webpage').create();
console.log('Setting error handling');
page.onConsoleMessage = function (msg) {
    console.log(msg);
};
page.onError = function (msg, trace) {
    console.log(msg);
    trace.forEach(function(item) {
        console.log('  ', item.file, ':', item.line);
    })
    phantom.exit();
}
console.log('Error handling is set');
console.log('Opening page');
page.open(url, function (status) {
    if (status != 'success') {
        console.log('F-' + status);
    } else {
        console.log('S-' + status); 
        //-------------------------------------------------     
        var jsLoc = '';
        jsLoc = 'jquery.min.js'; // to load local
        //jsLoc = 'http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; // to load remote      
        var act01 = function(pg){
            console.log('Function called');
            console.log('Page evaluating');
            console.log(pg);
            pg.evaluate(function() {
                var getElmById = function(id){
                    return document.getElementById(id);
                }           
                console.log('Page evaluate started');               
               //---
                var loginVar = '[email protected]';
                var pwdVar = 'itsmypass_445f4hd564hd56f46s'; 
                //---
                getElmById("username").value = loginVar;
                getElmById("passwd").value = pwdVar;
                getElmById("login_form").submit(); /// <<<<==== now its dont work !!!
                //---
            });
            console.log('Rendering');
            pg.render('ystsA.png');
            console.log('Rendered');
        }
        act01(page);
        //-------------------------------------------------
    }
    phantom.exit();
});

采纳答案by derickito

I know this question has already been answer about a year ago, but the answer didn't really address the issue. The reason for the error below:

我知道这个问题已经在大约一年前得到了回答,但答案并没有真正解决这个问题。错误原因如下:

"The page at https://login.yahoo.com/ran insecure content from http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js."

https://login.yahoo.com/上的页面运行了来自http://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js 的不安全内容 。”

Is that the login page is an https page and you're trying to load an http resource. If you change the url to https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.jsthis error will go away. Took a while to figure that out.

是登录页面是 https 页面,而您正在尝试加载 http 资源。如果您将 url 更改为https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js,此错误将消失。花了一段时间才弄清楚。

回答by Gil Barbara

A working version using google search.

使用谷歌搜索的工作版本。

var page, doSearch, displayResults;
page = require('webpage').create();

doSearch = function() {
    console.log('Searching...');
    page.evaluate(function() {
        $("input[name=q]").val('what is phantomjs');
        $("form").trigger('submit');
        return true;
    });
    page.render('phantomjs-searching.png');
};

displayResults = function() {
    console.log('Results...');
    page.evaluate(function() {
        $('h3 a').each(function(i) {
            console.log([i + 1, $(this).text(), ' // ' + $(this).attr('href')].join(': '));
        });
        return true;
    });
    page.render('phantomjs-results.png');
};

page.onLoadFinished = function(status) {
    if (status === 'success') {
        page.includeJs('http://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js', function() {
            if (!phantom.state) {
                doSearch();
                phantom.state = 'results';
            } else {
                displayResults();
                phantom.exit();
            }
        });
    } else {
        console.log('Connection failed.');
        phantom.exit();
    }
};

page.onConsoleMessage = function(msg) {
    console.log(msg);
};

page.open('http://google.com');

回答by lmeurs

Try the next code from http://snippets.aktagon.com/snippets/534-How-to-scrape-web-pages-with-PhantomJS-and-jQuery. It loads a local copy of jQuery, but can also use the jQuery instance loaded by the requested page.

尝试来自http://snippets.aktagon.com/snippets/534-How-to-scrape-web-pages-with-PhantomJS-and-jQuery的下一个代码。它加载 jQuery 的本地副本,但也可以使用被请求页面加载的 jQuery 实例。

var page = new WebPage(),
     url = 'http://localhost/a-search-form',
     stepIndex = 0;

 /**
  * From PhantomJS documentation:
  * This callback is invoked when there is a JavaScript console. The callback may accept up to three arguments: 
  * the string for the message, the line number, and the source identifier.
  */
 page.onConsoleMessage = function (msg, line, source) {
     console.log('console> ' + msg);
 };

 /**
  * From PhantomJS documentation:
  * This callback is invoked when there is a JavaScript alert. The only argument passed to the callback is the string for the message.
  */
 page.onAlert = function (msg) {
     console.log('alert!!> ' + msg);
 };

 // Callback is executed each time a page is loaded...
 page.open(url, function (status) {
   if (status === 'success') {
     // State is initially empty. State is persisted between page loads and can be used for identifying which page we're on.
     console.log('============================================');
     console.log('Step "' + stepIndex + '"');
     console.log('============================================');

     // Inject jQuery for scraping (you need to save jquery-1.6.1.min.js in the same folder as this file)
     page.injectJs('jquery-1.6.1.min.js');

     // Our "event loop"
     if(!phantom.state){
       initialize();
     } else {
       phantom.state();
     } 

     // Save screenshot for debugging purposes
     page.render("step" + stepIndex++ + ".png");
   }
 });

 // Step 1
 function initialize() {
   page.evaluate(function() {
     $('form#search input.query').val('Jebus saves');
     $('form#search').submit();
     console.log('Searching...');
   });
   // Phantom state doesn't change between page reloads
   // We use the state to store the search result handler, ie. the next step
   phantom.state = parseResults; 
 }

 // Step 2
 function parseResults() {
   page.evaluate(function() {
     $('#search-result a').each(function(index, link) {
       console.log($(link).attr('href'));
     })
     console.log('Parsed results');
   });
   // If there was a 3rd step we could point to another function
   // but we would have to reload the page for the callback to be called again
   phantom.exit(); 
 }

回答by h154sdfh656d4f

@lmeurs answer is very good but is not functional.
I used the answer to create something functional to you :) .

@lmeurs 的回答非常好,但不起作用。
我用答案来创造一些对你有用的东西:)。

var page = new WebPage();
var url = 'http://br.search.yahoo.com';
var stepIndex = 0;

page.onConsoleMessage = function (msg, line, source) { console.log('console> ' + msg); };

page.onAlert = function (msg) { console.log('alert!!> ' + msg); };

function takeShot(){
    console.log("TakingShot"); 
    page.render("step" + stepIndex + ".png");
    console.log("ShotTake");     
}

function step0() {
    console.log("step 00 enter");
    page.evaluate(function() {
        $("form [type='text']").val('its now sunday searching it');
        $("form [type='submit']").submit();     
    });
    console.log("step 00 exit");
}

function step1() {
    console.log("step 01 enter");
    page.evaluate(function() {
        $('#search-result a').each(function(index, link) {
            console.log($(link).attr('href'));
        })
    });
    console.log("step 01 exit");
    phantom.exit(); 
}

page.open(url, function (status) {
    console.log("[- STARTING -]");
    if (status === 'success') {
        var cmd = ""
        page.injectJs('jquery-1.6.1.min.js');
        while(true)
        {
            console.log("Step["+stepIndex+"] starting on ["+new Date()+"]");
            //cmd = "var x = step"+stepIndex+";"
            //console.log(cmd);
            //eval(cmd);
            switch(stepIndex){
                case 0:
                    step0();
                    break;
                case 1:
                    step1();
                    break;                  
            }
            takeShot();
            stepIndex++;
        }       
    }
});

回答by g4d564w56

There is a well know bug that PhantomJS cant load JQuery, will be hard to post some form data to server but you can select elements only using querySelectorAll like this example: how to scrape links with phantomjs

有一个众所周知的错误,即 PhantomJS 无法加载 JQuery,很难将一些表单数据发布到服务器,但您只能使用 querySelectorAll 来选择元素,如下例:如何使用 phantomjs 抓取链接