如何使此脚本在页面重新加载后继续执行?

huangapple go评论61阅读模式
英文:

How to make this script resume execution after page reload?

问题

初步情况共享

我被要求在一个我不拥有、也无法访问其API的网站上手动执行一个非常重复的操作。

我唯一希望自动化这些操作的方法是编写一些JavaScript代码,并在浏览器中执行它,以便自动化我本应手动完成的操作。

如果这个问题已经在其他地方得到了答案,请提前谅解,我是一个后端开发者,在我有限的前端知识中,我没有找到任何等价物。

问题的解释

假设我必须逐个将多个条目提交到一个表单中。我编写了以下代码(仅为演示目的而过于简化):

// 这个由上游服务生成的Json对象数组
var inputs = [
    {
       ...
    },
    {
       ...
    },
    {
       ...
    }
]

for (i = 0; i < inputs.length; i++) {
    fillSomeForms(inputs[i])
    clickSubmit() // <-- 这将导致页面重新加载,从而停止脚本执行
}

我在这里遇到的问题非常基本:在第一次for迭代后,当我调用clickSubmit()时,页面会重新加载(因为提交是一个POST请求,接着是重定向到“提交下一个”页面),因此JS停止执行。

我尝试在网上寻找类似的问题,我看到人们调整localStorage以恢复脚本的执行。
然而,这似乎是基于脚本作为前端代码资源的假设,而这对我来说并不适用(我不拥有这段代码,我只是将这个JS注入到浏览器的开发者控制台中并执行它以节省时间)。

有没有办法实现这个目的?我并不一定在寻找一个干净的解决方案,只是希望有一些可以使其工作并节省我们一些繁琐工作的方法(我在这里做的一切都不干净,但系统管理员不想提供访问实际提供此功能所需的REST API的权限)。

英文:

Preliminary context sharing

I am asked to manually perform a very repetitive action on a website that I do not own and for which I do not have any API access.

The only hope I have to automate these actions is to write some JavaScript and execute it on the browser just to automate the actions that I would be doing manually otherwise.

Please sorry in advance if this question already has an answer somewhere else, I'm a backend developer and in my limited knowledge of front-end I didn't manage to find any equivalence.

Explanation of the issue

Say I have to post several entries, one by one, into a form. I have written the following code (over simpified just for demonstration purposes):

//This array of Json objects is produced by an upstream service
var inputs = [
    {
       ...
    },
    {
       ...
    },
    {
       ...
    }
]

for (i = 0; i &lt; inputs.length; i++) {
    fillSomeForms(inputs[i])
    clickSubmit() //&lt;-- this will make the page reload, and so the script execution stop
}

The problem that I have here is very basic: after the first for iteration, when I invoke clickSubmit(), the page reloads (because the submission is a POST followed by a redirect to a "submit next" page) and so the JS stops executing.

I have tried to look around on the web for similar issues, and I've seen people tweaking the localStorage in order to resume the execution of their script.
However, that seems to assume the script being a resource of the front-end code, which is not the case for me (I don't own the code, I simply inject this JS into the browser's developer console and execute it to save some time).

Is there any way to reach this purpose? I am not necessarily looking for a clean solution, just for something that could get this work and spare us some monkey work (nothing of what I'm doing here is clean, but the system administrators do not want to provide access to the REST APIs that the platform actually provide to do so).

答案1

得分: 1

以下是代码的翻译部分:

当你将代码注入到控制台时,加载页面的一个副本到一个 iframe 中,然后从该副本提交表单:

const inputs = [ /* 一个方便的输入数组 */ ];
const pageCopy = document.body.appendChild( document.createElement( "iframe" ) );
pageCopy.addEventListener( "load", () => {
    // 页面副本已经加载/重新加载完毕,让我们提交更多的内容
    if( inputs.length > 0 ) {
        const moreInput = inputs.pop();
        console.log( "提交输入: ", moreInput );
        // 这本不应该起作用,但让我们将当前的 DOM 克隆到 iframe 中...
        pageCopy.contentDocument.body.parentElement.innerHTML =
            document.body.parentElement.innerHTML;
        fillSomeFormsInPageCopy( pageCopy.contentDocument, moreInput );
        pageCopy.contentDocument.querySelector( "#submitButtonId" ).click();
        console.log( "点击提交。将等待 iframe 完成重新加载..." );
        //好的,我们点击了提交按钮,iframe 正在重新加载。一旦它重新加载完毕,就可以准备提交更多的表单数据
    }
    else if( inputs.length === 0 ) {
        console.log( "已完成提交数组中的所有输入!" );
    }
} );
pageCopy.src = document.location.href;

请了解我无法测试这段代码(我甚至不确定 click() 事件是否可以跨越 iframe 边界触发,出于安全考虑,但我希望可以)。希望你能理解如何使用 pageCopy 的文档来查找表单元素并设置它们的值。例如,你可以使用以下方式:

pageCopy.contentDocument.getElementById( "form-entry-id-1" ).value =
    moreInput["form-entry-id-1"];

如果你需要更多帮助或有其他问题,请随时提出。

英文:

When you inject into the console, load a copy of the page into an iframe, and submit your forms from that copy:

const inputs = [ /* a convenient inputs array */ ];
const pageCopy = document.body.appendChild( document.createElement( &quot;iframe&quot; ) );
pageCopy.addEventListener( &quot;load&quot;, () =&gt; {
    //The page copy has finished loading / reloading, let&#39;s submit more stuff
    if( inputs.length &gt; 0 ) {
        const moreInput = inputs.pop();
        console.log( &quot;Submitting inputs: &quot;, moreInput );
        //this shouldn&#39;t work, but let&#39;s clone the current DOM into the iframe...
        pageCopy.contentDocument.body.parentElement.innerHTML =
            document.body.parentElement.innerHTML;
        fillSomeFormsInPageCopy( pageCopy.contentDocument, moreInput );
        pageCopy.contentDocument.querySelector( &quot;#submitButtonId&quot; ).click();
        console.log( &quot;Clicked submit. Will wait for iframe to finish reloading...&quot; );
        //Okay, we clicked and the iframe is reloading. This event will fire again as soon as it&#39;s done reloading, ready to submit more form data
    }
    else if( inputs.length === 0 ) {
        console.log( &quot;Finished submitting all the inputs in the array!&quot; );
    }
} );
pageCopy.src = document.location.href;

Please understand I can't test this code. (I'm not even sure the click() event can be fired across an iframe boundary, for security, but I hope it can.)
Hopefully you can understand how to use the pageCopy's document to find your form elements and set their values. E.g., you can use

pageCopy.contentDocument.getElementById( &quot;form-entry-id-1&quot; ).value =
    moreInput[ &quot;form-entry-id-1&quot; ];

答案2

得分: 0

在这种情况下,如果将来有人需要帮助,我最终成功通过每次循环迭代时打开一个新选项卡(并在该选项卡中操作)来解决了这个问题。

类似于这样:

while (inputs.length > 0) {
    const singleInput = inputs.pop();
    const newWindow = window.open('about:blank', '_blank');
    newWindow.addEventListener('load', () => {
        newWindow.document.body.parentElement.innerHTML = document.body.parentElement.innerHTML;
        fillForm(newWindow.document, singleInput) // <-- 填充表单的函数使用传递的文档执行不同的获取/设置操作
        newWindow.document.getElementById("submit-button").click();
    });
}
英文:

In case it may help someone in the future, I finally was able to work around the problem by opening a new tab (and working in that tab) per iteration of my loop.

Something like this:

while (inputs.length &gt; 0) {
    const singleInput = inputs.pop();
    const newWindow = window.open(&#39;about:blank&#39;, &#39;_blank&#39;);
    newWindow.addEventListener(&#39;load&#39;, () =&gt; {
        newWindow.document.body.parentElement.innerHTML = document.body.parentElement.innerHTML;
        fillForm(newWindow.document, singleInput) //&lt;-- the function fill form uses the document in parameter to perform the different get/set
        newWindow.document.getElementById(&quot;submit-button&quot;).click();
    });
}

huangapple
  • 本文由 发表于 2023年2月16日 18:44:47
  • 转载请务必保留本文链接:https://go.coder-hub.com/75471121.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定