Abrufen des Quell-HTML der aktuellen Seite aus der Chrome-Erweiterung

85

Ich habe eine Chromverlängerung. Ich muss aus der HTML-Quelle der aktuellen Seite analysieren. Ich habe hier alle Arten von Lösungen mit Hintergrundseiten und Inhaltsskripten gefunden, aber keine hat mir geholfen. Folgendes habe ich bisher:
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);
    }
});

Die Warnung warnt immer undefiniert. Auch wenn ich in der Datei content.js die Rückruffunktion ändere:

callback('hello'); 

immer noch das gleiche Ergebnis. Was mache ich falsch? Vielleicht gehe ich das falsch an. Was ich wirklich brauche, ist das. Wenn der Benutzer das Erweiterungs-Popup öffnet (und nur dann), benötige ich HTML der aktuellen Seite, damit ich es analysieren kann. irgendwelche Vorschläge?

Herr T.
quelle
Ein Problem ist, dass der Code auf Ihrer Hintergrundseite sofort ausgeführt wird (bevor die Inhaltsskripte eingefügt werden). Eine sehr ähnliche / doppelte Frage wurde bereits gestellt. Schauen Sie sich die Antwort unter Öffnen Sie einen neuen Google Chrome-Tab an und holen Sie sich die Quelle .
Rob W
Danke für deine Antwort rob. Ich habe die Codesegmente in Ihren angehängten Link kopiert, aber es funktioniert immer noch nicht. Das Problem ist, dass meine Erweiterung ein Popup ist und ich den HTML-Code nur erhalten muss, wenn der Benutzer meine Erweiterung öffnet. Wenn der aktuelle Tab beispielsweise facebook.com ist, rufe ich nur beim Öffnen meiner Erweiterung die HTML-Quelle in meine js-Datei ab (nicht das Inhaltsskript oder die Hintergrundseite).
Herr T.
Aktualisieren Sie Ihre Frage mit Ihrem aktuellen Code. Der Code muss Kommentare enthalten, die das Problem hervorheben.
Rob W

Antworten:

155

Fügen Sie ein Skript in die Seite ein, von der Sie die Quelle erhalten möchten, und senden Sie es an das Popup zurück.

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)
});
PAEz
quelle
@ Gil Tankus Tut mir leid für meinen ersten Beitrag, habe den Kommentaren (wieder) nicht genug Aufmerksamkeit geschenkt und am Ende nur wieder aufgeflogen, was Rob W gesagt hat. Der neue Beitrag sollte das haben, was Sie wollten.
PAEz
Vielen Dank, Ihre Antwort war wirklich hilfreich. Mein Problem ist, dass die on onMessage asynchron erfolgt. In meinem Popup habe ich alle möglichen anderen Dinge, die sich auf den Quell-HTML-Code beziehen. Wie kann ich die Quelle in einer globalen Variablen speichern und erst dann mit der Funktion zum Laden von Seiten fortfahren?
Herr T.
Ich glaube nicht, dass du kannst. Sie müssen es entweder in den Rückrufcode oder in eine Funktion einfügen und das im Rückruf aufrufen ... wenn nur JS einen gotoBefehl hätte, ja? ; P
PAEz
19
Warum nicht einfach so etwas wie document.documentElement.outerHTML anstelle der DOMtoString-Funktion?
DJFM
@djfm Das wäre fast die ganze Zeit in Ordnung. Es ist nur so, dass nach dem, was ich sagen konnte, Rob Ws Funktion vollständiger ist ... gibt den Doctype zurück, zum Beispiel, dass Ihre Lösung dies nicht tut, Ihre bekommt nur den HTML-Teil.
PAEz