检查我的javascript是否已加载到网站上


Check if my javascript is loaded on a site

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

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

有没有一种方法可以检查外部网站上是否通过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');
?>

我也会把它发布在这里。既然是我让你上了phantomjs,那么给你提供我认为是解决你问题的答案才是公平的
以下脚本在无头幻影浏览器中打开一个页面,记录该页面在实际浏览器中会产生的任何控制台消息(使用onConsoleMessage事件),如果页面无法加载,它还会记录错误,如果页面打开时没有出现问题,它会检查该页面上的所有<script>标记,查找您的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处理程序处理这个异常。这可能是一种绕过沙盒限制的方法,在某种程度上,如果它们导致无限循环问题发生的话。

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

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

使用PHP:

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

使用JavaScript

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

自托管

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

是否可以检查javascript是否正在运行而没有错误

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

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

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

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

一个迂回的方法,或者更简单的方法是创建一个具有唯一名称的伪对象定义,比如"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();

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

注意:这实际上是一个幼稚的解决方案,因为有些人可能会在脚本中创建一个同名对象此外,它毫无理由地污染全局命名空间