node.js - 使用 PhantomJS 处理多个用户对多个远程 Web 表单的请求

标签 node.js express phantomjs headless-browser nightmare

我使用 NightmareJS 创建了一个 ExpressJS 应用程序,它有一个表单,当我们填写表单并提交时,它会向一些远程表单发送请求并计算数据并返回这些结果。但问题是它仅在单个客户提交表单时有效。当多个客户同时提交表单时,它不起作用。这可能是什么原因以及如何解决?

前端JS脚本

$(document).ready(function () {

$("#calculate-form").submit(function (event) {
    var request;

    if (request) {
        request.abort();
    }

    var $form = $(this);

    var $inputs = $form.find("input, select, button, textarea");

    var serializedData = $form.serialize();

    $inputs.prop("disabled", true);

    form1(request, serializedData, $inputs, '/example1', '#form1');

    function form1(request, serializedData, inputs, appUrl, displayElement)
    {
        request = $.ajax({
            url: appUrl,
            type: "post",
            data: serializedData
        });



        request.done(function (response) {
            $(displayElement).text(response.value);

            form2(request, serializedData, $inputs, '/example2', '#form2');

            function form2(request, serializedData, inputs, appUrl, displayElement)
            {
                request = $.ajax({
                    url: appUrl,
                    type: "post",
                    data: serializedData
                });

                request.done(function (response) {
                    $(displayElement).text(response.value);
                });

                request.fail(function (jqXHR, textStatus, errorThrown) {
                    console.log("Failed");
                });
            }
        });

        request.fail(function (jqXHR, textStatus, errorThrown) {
            console.log("Failed");
        });
    }

    event.preventDefault();
});
});

ExpressJS 索引脚本

var express = require('express');
var app = express();
var phantom = require('phantom');
var bodyParser = require('body-parser');
var Nightmare = require('nightmare');

app.use(bodyParser.urlencoded({
  extended: true
}));
app.set('port', (process.env.PORT || 5000));
app.use(express.static(__dirname + '/'));
app.engine('html', require('ejs').renderFile);
app.get('/', function (request, response) {
   response.render('index.html');
});
app.listen(app.get('port'), function () {
   console.log('Scrapper is running on port', app.get('port'));
});

require('./form1')(app, Nightmare);
require('./form2')(app, Nightmare);

ExpressJS form1 脚本

module.exports = function (app, Nightmare) {

var nightmare1 = Nightmare({
    show: true
});


app.post('/example1', function (req, res) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.setHeader('Content-Type', 'application/json');
    try
    {
        if (req.method === 'POST') {
            var requestParams = req.body;
            nightmare1

                    .goto('https://example1.com/form')
                    .evaluate(function () {
                        var select = document.querySelector('#RepaymentMethod');
                        select.value = "1";
                        select.dispatchEvent(new Event('change'));
                    })
                    .wait("#formbtn-1")
                    .evaluate(function () {

                        document.getElementById('inputfield_1').value = "inputfield-1-Value";

                        document.getElementById('btnSubmitform').click();

                    })
                    .wait("#resultvalue")
                    .evaluate(function () {

                        var str = document.querySelector('#resultvalue').innerText;
                        return res;

                    })
                    .end()


                    .then(function (form1) {
                        res.send({value: form1});
                        nightmare1.halt();
                    })

                    .catch(function (error) {
                        res.send({'error': error});
                        nightmare1.halt();
                    });
        }
    } catch (err)
    {
        res.sendStatus(400).send(err);
        nightmare1.halt();
        process.exit();
    }
});
}

ExpressJS form2 脚本

module.exports = function (app, Nightmare) {

var nightmare2 = Nightmare({
    show: true
});


app.post('/example2', function (req, res) {
    res.header("Access-Control-Allow-Origin", "*");
    res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept");
    res.setHeader('Content-Type', 'application/json');
    try
    {
        if (req.method === 'POST') {
            var requestParams = req.body;
            nightmare2

                    .goto('https://example2.com/form')
                    .evaluate(function () {
                        var select = document.querySelector('#RepaymentMethod');
                        select.value = "10";
                        select.dispatchEvent(new Event('change'));
                    })
                    .wait("#formbtn-1")
                    .evaluate(function () {

                        document.getElementById('inputfield_1').value = "inputfield-1-Value";
                        document.getElementById('inputfield_2').value = "inputfield-2-Value";

                        document.getElementById('btnSubmitform').click();

                    })
                    .wait("#resultvalue")
                    .evaluate(function () {

                        var str = document.querySelector('#resultvalue').innerText;
                        return res;

                    })
                    .end()


                    .then(function (form2) {
                        res.send({value: form2});
                        nightmare2.halt();
                        process.exit();
                    })

                    .catch(function (error) {
                        res.send({'error': error});
                        nightmare2.halt();
                        process.exit();  
                    });
        }
    } catch (err)
    {
        res.sendStatus(400).send(err);
        nightmare2.halt();
        process.exit();
    }
});
}

最佳答案

根据您发布的示例,您尝试在多个请求中重复使用同一个 Nightmare 实例。如果您有多个请求进来,这将不起作用,后续请求的操作将添加到当前执行的上下文中。这会更加复杂,因为您还 .end() 实例,导致 Nightmare 实例在初始请求后无法使用。

如果您将 Nightmare 实例化移动到 Express post 方法中,您可能会有更好的运气,但要小心:此方法的扩展性不会特别好。

关于node.js - 使用 PhantomJS 处理多个用户对多个远程 Web 表单的请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42398621/

相关文章:

python - 从 Selenium 中的 url 下载 CSV?

Node.js IPv6 问题

node.js - stub 类实例方法返回已解析的 Promise(使用 Sinon)

node.js - 我无法使用 ejs 渲染我的模板 css

javascript - 如何从快速渲染的 ejs 网页调用 node.js 函数

css - Node express + CSS

python - 从 HTML 代码获取图像宽度

PhantomJS 无法打开本地文件

javascript - 获取有关数据响应的 TCP 套接字特定数据

node.js - nightmare.js,在.evaluate上,这给了我一个关于 Node 的错误