Chrome拡張機能から現在のページのソースHTMLを取得する


86

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が必要です。助言がありますか?


問題は、バックグラウンドページのコードがすぐに(コンテンツスクリプトが挿入される前に)実行されることです。非常に類似した/重複した質問が以前に尋ねられました。新しいGoogleChromeタブ開き、ソースを取得するで答えを見てください。
ロブW

返信をありがとうございます。添付リンクのコードセグメントをコピーしましたが、それでも機能しません。問題は、私の拡張機能がポップアップであり、ユーザーが私の拡張機能を開いたときにのみHTMLを取得する必要があることです。たとえば、現在のタブがfacebook.comの場合、拡張機能を開いたときにのみ、(コンテンツスクリプトやバックグラウンドページではなく)jsファイルのhtmlソースを取得します。
Mr T.

現在のコードで質問を更新します。コードには、問題を強調するコメントを含める必要があります。
ロブW

回答:


157

ソースを取得するページにスクリプトを挿入し、ポップアップにメッセージを送り返します。

マニフェスト.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>"]
}

ポップアップ.html

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

ポップアップ.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最初の投稿で申し訳ありませんが、コメントに十分な注意を払わず(再び)、RobWが言ったことを逆流させてしまいました。新しい投稿には、必要なものが含まれているはずです。
PAEz 2012

おかげで、あなたの答えは本当に役に立ちました、私の問題はononMessageが非同期で起こるということです。私のポップアップには、ソースHTMLを中継する他のあらゆる種類のものがあります。ソースをグローバル変数に保存してから、ページのオンロード機能を続行するにはどうすればよいですか?
Mr T.

私はあなたができるとは思わない。あなたはそれをコールバックコードまたは関数に入れてコールバックでそれを呼び出さなければならないgotoでしょう... JSだけがコマンドayeを持っていたら?; P
PAEz 2012

21
DOMtoString関数の代わりにdocument.documentElement.outerHTMLのようなものだけではないのはなぜですか?
djfm 2015年

@djfmそれはほとんどいつも大丈夫でしょう。それは、Rob Wの関数がより完全であると私が言えることから、たとえば、ソリューションが返さないdoctypeを返し、html部分のみを取得しているということです。
PAEz 2015年

0

これが私の解決策です:

chrome.runtime.onMessage.addListener(function(request, sender) {
        if (request.action == "getSource") {
            this.pageSource = request.source;
            var title = this.pageSource.match(/<title[^>]*>([^<]+)<\/title>/)[1];
            alert(title)
        }
    });

    chrome.tabs.query({ active: true, currentWindow: true }, tabs => {
        chrome.tabs.executeScript(
            tabs[0].id,
            { code: 'var s = document.documentElement.outerHTML; chrome.runtime.sendMessage({action: "getSource", source: s});' }
        );
    });
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.