从Chrome扩展程序获取当前页面的源HTML


85

我有一个Chrome扩展程序。我需要从当前页面的HTML源进行分析。我在这里找到了带有背景页面和内容脚本的各种解决方案,但没有一个帮助我。这是我到目前为止所拥有的:
manifest.json:

{
  "name": "Extension",
  "version": "1.0",
  "description": "Extension",
  "browser_action": {
    "default_icon": "bmarkred.ico",
    "popup": "Test.html"
  },
  "content_scripts": [
    {
      "matches": ["http://*/*"],
      "js": ["content.js"]
    }
  ],
  "background": {
    "page": "backgroundPage.html"
  },
  "permissions": [
    "cookies",
    "tabs",
    "http://*/*", 
    "https://*/*"
  ]
}

background.html:

<html>
<head>
<script type="text/javascript">
    try {
        chrome.tabs.getSelected(null, function (tab) {
            chrome.tabs.sendRequest(tab.id, {action: "getSource"}, function(source) {
                alert(source);
            });
        });
    }
    catch (ex) {
        alert(ex);
    }
</script>
</head>
</html>

content.js:

chrome.extension.onRequest.addListener(function(request, sender, callback) {
    if (request.action == "getSource") {
        callback(document.getElementsByTagName('html')[0].innerHTML);
    }
});

警报始终警报未定义。即使我在content.js文件中将回调函数更改为:

callback('hello'); 

结果还是一样。我究竟做错了什么?也许我走错路了。我真正需要的是这个。当用户打开扩展弹出窗口时(只有那时),我需要当前页面的HTML,以便可以对其进行分析。有什么建议么?


问题在于后台页面中的代码会立即运行(在注入内容脚本之前)。之前有人问过一个非常相似/重复的问题。在“打开新的Google Chrome浏览器”标签并获取源代码中查看答案。
罗伯W

谢谢您的回覆。我在您的附加链接中复制了代码段,但仍然无法正常工作。问题是我的扩展程序是一个弹出窗口,仅当用户打开我的扩展程序时,我才需要获取HTML。例如,如果当前选项卡是facebook.com,则仅当我打开扩展名时,我才会将html源代码检索到我的js文件中(而不是内容脚本或背景页面)。
T.先生

使用当前代码更新您的问题。该代码必须包含突出显示该问题的注释。
罗伯W

Answers:


155

将脚本插入到您要从中获取源代码的页面中,并将其发送回弹出窗口...。

manifest.json

{
  "name": "Get pages source",
  "version": "1.0",
  "manifest_version": 2,
  "description": "Get pages source from a popup",
  "browser_action": {
    "default_icon": "icon.png",
    "default_popup": "popup.html"
  },
  "permissions": ["tabs", "<all_urls>"]
}

popup.html

<!DOCTYPE html>
<html style=''>
<head>
<script src='popup.js'></script>
</head>
<body style="width:400px;">
<div id='message'>Injecting Script....</div>
</body>
</html>

popup.js

chrome.runtime.onMessage.addListener(function(request, sender) {
  if (request.action == "getSource") {
    message.innerText = request.source;
  }
});

function onWindowLoad() {

  var message = document.querySelector('#message');

  chrome.tabs.executeScript(null, {
    file: "getPagesSource.js"
  }, function() {
    // If you try and inject into an extensions page or the webstore/NTP you'll get an error
    if (chrome.runtime.lastError) {
      message.innerText = 'There was an error injecting script : \n' + chrome.runtime.lastError.message;
    }
  });

}

window.onload = onWindowLoad;

getPagesSource.js

// @author Rob W <http://stackoverflow.com/users/938089/rob-w>
// Demo: var serialized_html = DOMtoString(document);

function DOMtoString(document_root) {
    var html = '',
        node = document_root.firstChild;
    while (node) {
        switch (node.nodeType) {
        case Node.ELEMENT_NODE:
            html += node.outerHTML;
            break;
        case Node.TEXT_NODE:
            html += node.nodeValue;
            break;
        case Node.CDATA_SECTION_NODE:
            html += '<![CDATA[' + node.nodeValue + ']]>';
            break;
        case Node.COMMENT_NODE:
            html += '<!--' + node.nodeValue + '-->';
            break;
        case Node.DOCUMENT_TYPE_NODE:
            // (X)HTML documents are identified by public identifiers
            html += "<!DOCTYPE " + node.name + (node.publicId ? ' PUBLIC "' + node.publicId + '"' : '') + (!node.publicId && node.systemId ? ' SYSTEM' : '') + (node.systemId ? ' "' + node.systemId + '"' : '') + '>\n';
            break;
        }
        node = node.nextSibling;
    }
    return html;
}

chrome.runtime.sendMessage({
    action: "getSource",
    source: DOMtoString(document)
});

@吉尔·坦库斯(Gil Tankus)很抱歉,我的第一篇博文(再次)没有对评论给予足够的重视,最终只是反驳了罗伯·W(Rob W)所说的话。新帖子应该有您想要的。
PAEz

谢谢,您的回答确实很有帮助,我的问题是onMessage发生异步。在我的弹出窗口中,我还有各种其他可以在源HTML上进行中继的东西。我如何才能将源保存在全局变量中,然后才继续使用页面onload函数?
T.先生

我认为你不能。您要么将其放入回调代码中,要么放入函数中,然后在回调中调用它……如果只有JS有goto命令的话?; P
PAEz 2012年

19
为什么不只是像document.documentElement.outerHTML这样的东西,而不是DOMtoString函数?
djfm 2015年

@djfm几乎所有时间都很好。只是从我可以告诉Rob W的功能来看,它是更完整的……例如返回您的解决方案没有的doctype,您的仅得到html部分。
PAEz
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.