如何将用户脚本注入嵌入式网页内容?

Posted

技术标签:

【中文标题】如何将用户脚本注入嵌入式网页内容?【英文标题】:How to inject userscripts into embedded web page content? 【发布时间】:2019-02-01 08:16:25 【问题描述】:

单击链接以打开嵌入式网页后,我想注入一个用户脚本。具体来说,我想知道我应该如何注入这个脚本:

Array.from(document.querySelectorAll('span')).filter(i => /(\d+)\spoint/.test(i.innerhtml)).forEach(i => i.style.display = 'none');

Array.from(document.querySelectorAll('div')).filter(i => /moreComments-/.test(i.id)).forEach(i => i.querySelector('p').click());

setTimeout(function() 
    Array.from(document.querySelectorAll('span')).filter(i => /(\d+)\spoint/.test(i.innerHTML)).forEach(i => i.style.display = 'none');
,7000)

进入所有可嵌入的 Reddit 子页面,即从 subreddit 的主页加载的所有链接线程:

与标准完全加载页面相比,嵌入 Reddit 子页面的图片

我认为这需要一个事件侦听器或MutationObserver,但我不知道如何指定解决方案。阅读 Reddit 源代码非常令人困惑,而且我不是编码员。这只是我认为对我自己和其他日常网络用户有用的知识。

解决此类问题的正确步骤是什么?我应该考虑什么样的代码?

【问题讨论】:

【参考方案1】:

您需要在选定的一组页面节点上处理用户脚本。由于您的代码在每个页面加载事件中只执行一次,因此稍后动态加载的节点不受影响。

有几种方法可以实现您的目标。最简单的方法之一是使用setInterval 函数。这会定期调用您的函数(通过使用合理的时间跨度,例如 500 毫秒)。使用此功能,您必须选择所需的节点并仅处理新到达的节点。你可以用_is_processed 属性来标记你的节点的DOM 对象。最后,这可以包装到另一个函数中,比如doForEachOnce。例如:

function doForEachOnce(list,theFunc) 
    list.forEach(i => 
        if (!i._is_processed)  i._is_processed = true; return theFunc(i);  else  return null; 
    );


doForEachOnce(Array.from(document.querySelectorAll('span')).filter(i => /(\d+)\spoint/.test(i.innerHTML)), i => i.style.display = 'none');
doForEachOnce(Array.from(document.querySelectorAll('div')).filter(i => /moreComments-/.test(i.id)), i => i.querySelector('p').click());

setInterval(function() 
  doForEachOnce(Array.from(document.querySelectorAll('span')).filter(i => /(\d+)\spoint/.test(i.innerHTML)), i => i.style.display = 'none');
,500);

我用 Tampermonkey 成功测试了这个用户脚本。它扩展所有 cmets,在页面加载时隐藏业力,然后为每个新来者再次隐藏业力。希望这是你需要的。

【讨论】:

优秀的方法,我相信。它按预期工作,似乎没有任何性能问题。感谢您的贡献。【参考方案2】:

你的问题太笼统了,但我假设你问的是一些基本的问题。如果针对某些特定平台,请澄清您的问题。

我假设您只想将 javascript 代码注入 Web HTML 页面或 HTML 页面的一部分。

通常通过脚本标签完成

    <script>
    /* Your code is here */
    Array.from(document.querySelectorAll.......
    </script>

要强制链接调用您的代码,您必须将代码包装在函数内并将标签的 href 属性格式化为 javascript:func_name()

    <script>
    function my_func()
    
      /* Your code is here */
      Array.from(document.querySelectorAll.......
    
    </script>
    <a href="javascript:my_func()">click me</a>

【讨论】:

我使用 Tampermonkey 将脚本自动注入到所有 Reddit 页面中。但是,这仅适用于单个页面加载事件。它不适用于嵌入式子页面等动态加载的内容。我不确定如何定位相关链接,以便在每个嵌入页面加载事件后重新应用脚本。

以上是关于如何将用户脚本注入嵌入式网页内容?的主要内容,如果未能解决你的问题,请参考以下文章

什么是XSS攻击?什么是SQL注入攻击?什么是CSRF攻击?

XSS SQL CSRF

在网页上的所有 iframe 中注入 iframe 的内容脚本

如何在 iOS 上注入用户脚本?

XSS跨站脚本总结

web安全之XSS注入