【问题标题】:Check if my javascript is loaded on a site检查我的 javascript 是否加载到网站上
【发布时间】:2013-08-20 07:56:48
【问题描述】:

我以前问过这个问题,但似乎我被误解了,因此我决定再问一次,但这次有很多信息:

对于懒惰的读者,我的目标是:

有没有办法通过 PHP 或 Ajax 检查是否在外部网站上启用了 javascript

详细说明:

好的,我的公司有很多客户,当这些客户在我们的网站上注册时,他们会收到一个javascript。然后他们可以在自己的网站上使用这个script 来获得一些额外的功能。

现在客户拥有的所有网站都存储在我们的 CMS 系统中(就像他们拥有与我们签署的所有网站的列表一样)。

现在我的老板给了我以下任务:

我们需要一个功能,以便用户可以按下“测试”按钮,系统将测试 javascript 是否在他们的网站上并且可以正常工作(即是否有另一个脚本阻止了我们的)。

现在过去几天,我一直试图在web 上找到类似的案例,我唯一得到的建议是 Phantomjs,但是没有关于如何接近我想要的例子达到。

所以我的问题是:

  1. 是否可以检查网站是否有特定的javascript。
  2. 是否可以检查 javascript 是否运行无错误(控制台是否抛出错误)

希望这次不会被误会:) 有任何问题请留言,我会尽快回复!

phantomJs 解决方案(最初由 Elias 发布)

这是我的代码:

   var page = require('webpage').create();
page.onConsoleMessage = function( message, line, srcId)
{//show console errors for page
    console.log('Page has errors showing in console: ' + msg
        + ' (line: ' + (line || '?') + ', id: ' + srcId + ')');
};
page.open('http://www.marcrasmussen.com',function(status)
{
    if (status != 'success')
    {//can't load page
        console.log('Failed to open page: ' + status);
        phantom.exit();
        return;
    }
    var reslt = page.evaluate(function()
    {
        var usesOurScript = false,
            scripts = document.querySelectorAll('script');//get all script tags
        Array.forEach.apply(scripts, [function(elem)
        {//check all loaded scripts
              if (/jquery\.js/.js.js.test(elem.getAttribute('src')))
            {//this src attribute refers your script
                usesOurScript = true;//set to true
            }
        }]);
        return {page: location.href, found: usesOurScript};//return its href and the use-status
    });
    //script was found? adjust message
    reslt.found = (reslt.found ? ' uses ' : ' does not use ') + 'our script!';
    console.log(reslt.page + reslt.found);//logs url does not use || uses our script
    phantom.exit();
});

当我从 php 运行它时,它没有任何输出,它只会一直运行:

Test.php

<?php echo shell_exec('phantomjs hello.js');

?>

【问题讨论】:

  • 这可能更容易通过加载到客户端站点的代码来实现。 IE。当一个或多个函数发生错误时,让该代码对您的数据库执行 POST。
  • 我能想到的唯一方法实际上是访问站点并检查控制台。或者让您的 js(您提供给客户端)通过 ajax 将错误消息发送到您服务器上的脚本
  • @class 我如何不手动检查站点的控制台?
  • @MarcRasmussen 据我所知,我认为你做不到。
  • 或者您可以将 js 托管在您的服务器上,并检查 js 文件何时被访问以及由谁访问的日志,并实现一个错误函数以将错误发布到您服务器上的脚本中

标签: php javascript testing web phantomjs


【解决方案1】:

我也会在这里发布。由于我是让您使用 phantomjs 的人,因此为您提供我认为是解决您问题的答案是公平的。
以下脚本在无头幻象浏览器中打开一个页面,记录该页面在实际浏览器中产生的任何控制台消息(使用onConsoleMessage 事件),如果页面无法加载,它还会记录错误,并且,如果页面打开没有问题,它会检查该页面上的所有 &lt;script&gt; 标记,查找您的 javascript 文件。

var page = require('webpage').create();
page.onConsoleMessage = function( message, line, srcId)
{//show console errors for page
    console.log('Page has errors showing in console: ' + msg
                + ' (line: ' + (line || '?') + ', id: ' + srcId + ')');
};
page.open('http://www.your-url-here.org',function(status)
{
    if (status != 'success')
    {//can't load page
        console.log('Failed to open page: ' + status);
        phantom.exit();
        return;
    }
    var reslt = page.evaluate(function()
    {
        var usesOurScript = false,
        scripts = document.querySelectorAll('script');//get all script tags
        /* Array.forEach is causing errors, as it turns out...
        Array.forEach.apply(scripts, [function(elem)
        {//check all loaded scripts
            if (/yourScriptName\.js/.test(elem.getAttribute('src')))
            {//this src attribute refers your script
                usesOurScript = true;//set to true
            }
        }]);*/
        for (var i=0;i<scripts.length;i++)
        {
            if (/yourScriptName\.js/.test(scripts[i].getAttribute('src')))
            {
                return {page: location.href, found: true};
            }
        }
        return {page: location.href, found: false};
    });
    //script was found? adjust message
    reslt.found = (reslt.found ? ' uses ' : ' does not use ') + 'our script!';
    console.log(reslt.page + reslt.found);//logs url does not use || uses our script
    phantom.exit();
});

如果该文件执行 jQ 之类的操作(创建对某个对象的全局引用),您甚至可以将其添加到 page.evaluate 回调中:

    var reslt = page.evaluate(function()
    {//this code will behave like it's running on the target page
        var libs = {jQuery: ($ || jQuery),
                    myLib: ourLibsGlobalName};
        return libs;
    });
    if (reslt.jQuery instanceof Object)
    {
        console.log('client uses jQ');
    }
    if (reslt.myLib instanceof Object)
    {
        console.log('client uses our lib, successfuly');//wouldn't be accessible if it contained errors
    }
    console.log(reslt.myLib);//shows full object, so you can verify it's the right one

注意:
这段代码未经测试,我只是在脑海中写下它。它可能包含愚蠢的错字。这不是您所有祈祷的可复制粘贴的答案。
我确实相信page.evaluate 回调能够返回一些东西,但是:它在加载页面的上下文中运行,并且是沙盒,所以你可能必须强制一个错误:

page.evaluate(function()
{
    Array.forEach(document.querySelectorAll('script'), [function(elem)
    {
        if (/yourScript\.js/.test(elem.getAttribute('src')))
        {
            throw {message: 'Script found',
                   nodeSrc: elem.getAttribute('src'),
                   pageUrl: location.href,
                   myLib  : yourGlobalVar}//<-- cf remarks on jQ-like usage
        }
    }]);
});

通过抛出这个没有被捕获的自定义错误,它最终会出现在控制台中,你可以强制page.onConsoleMessage 处理程序处理这个异常。这可能是一种绕过沙盒限制的方法,在某种程度上,如果它们导致发生无限循环问题。

【讨论】:

  • 是否应该将 /yourScriptName\ 替换为:myjavascript 或 /myjavascript\ ?
  • @MarcRasmussen:它是一个正则表达式,因此如果您要查找的脚本是 jquery.min.js,则应替换为 /jquery\.min\.js/。将其更改为 /jquery\.(min\.)?js/ 以匹配 jquery.jsjquery.min.js...
  • 我就是这么想的,但是当我在自己的网站 (www.marcrasmussen.dk) 上运行它时,我没有得到任何反馈(没有任何记录),它只会一直运行下去!'跨度>
  • @MarcRasmussen:您在网站上运行的具体内容是什么?用一个简单的循环替换Array.forEach.apply-bit 可能会更好,并且只记录每次迭代。我只是在脑海中写下这段代码,根本没有测试,所以那里可能有一些错误......
  • @MarcRasmussen:那么,将Array.forEach 替换为常规for (var i=0;i&lt;scripts.length;i++)。那是标准的JS调试!无论如何,我已经编辑了我的代码,所以现在应该解决问题
【解决方案2】:

是否可以检查网站是否有特定的 JavaScript?

你可以做两件事,我认为使用 JavaScript 的那件事会更容易实现。

使用 PHP:

  • 从数据库中的 URL 获取内容
  • 将其加载到 DOMDocument 并搜索代码的特定部分
  • 从该文档中提取所有外部 JavaScript 文件
    • 也获取它们并在其中搜索特定代码部分

使用 JavaScript

  • 在构造函数或启动方法中实现 AJAX 请求
  • 发送执行脚本的当前域并将其与数据库中的列表进行比较

自托管

  • 正如在编写此答案时所讨论的,这是另一种可能性,因为您的日志可以显示此脚本访问的所有页面

是否可以检查 javascript 是否正常运行?

这个有点复杂,因为你在运行时检查过这个。想象一下,您的脚本的用户扩展或修改了您的代码,或者只是以错误的方式使用它,或者与您的代码有冲突。也许这段代码永远不会到达,因为它调用了一些可能会或可能不会触发的用户交互。

当发生错误时,一种可能性是向您发送 AJAX 请求。为此,您可以查看window.onerror

window.onerror = function(message, url, lineNumber) {}

这将为您提供一些详细信息,您可以使用 AJAX 请求将这些信息传递给您的服务器。

【讨论】:

  • 使用 PHP 不会验证任何 JS,也不会考虑使用 require.js 或lazyload 之类的页面...
  • @EliasVanOotegem 我从来没有说过,使用 PHP 获取页面将执行任何 JavaScript 代码。但是您可以搜索脚本的一部分是否出现在某个地方。是的,使用延迟加载时它可能会失败。这就是为什么我会推荐 JavaScript 解决方案而不是 PHP 解决方案。当 OP 询问是否以及如何也可以使用 PHP 时,我也简单地回答了这部分。
【解决方案3】:

一个环形交叉路口或更简单的方法是创建一个具有唯一名称的虚拟对象定义,例如“your_company_name_”+some_hash。像 abc_45xcd。

//your custom js file

//BEWARE! this is global namespace. 

function abc_45xcd(){
      console.log('abc_45scd custom js is loaded');
}

当你点击测试按钮时,你可以尝试创建一个新对象

   var x = new abc_45scd();

您可以检查构造函数和类型以检查它是否是您自己的自定义虚拟对象。

注意:这实际上是一个幼稚的解决方案,因为有些人可能会在他们的脚本中创建一个同名的对象。 而且,它会无缘无故地污染全局命名空间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-01-06
    相关资源
    最近更新 更多