Lấy HTML nguồn của trang hiện tại từ tiện ích mở rộng chrome


85

Tôi có một phần mở rộng chrome. tôi cần phân tích từ nguồn HTML của trang hiện tại. Tôi đã tìm thấy ở đây tất cả các loại giải pháp với các trang nền và tập lệnh nội dung nhưng không có giải pháp nào giúp được tôi. đây là những gì tôi có cho đến nay:
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);
    }
});

Cảnh báo luôn cảnh báo không xác định. ngay cả khi tôi thay đổi trong tệp content.js hàm gọi lại thành:

callback('hello'); 

vẫn là kết quả tương tự. Tôi đang làm gì sai? có lẽ tôi đang đi sai cách. whay tôi thực sự cần là cái này. Khi người dùng mở cửa sổ bật lên tiện ích mở rộng (và chỉ sau đó), tôi cần HTML của trang hiện tại để có thể phân tích nó. bất kỳ đề xuất?


Một vấn đề là mã trong trang nền của bạn được chạy ngay lập tức (trước khi các tập lệnh nội dung được đưa vào). Một câu hỏi rất giống / trùng lặp đã được hỏi trước đây; Hãy xem câu trả lời tại Mở tab Google Chrome mới và lấy nguồn .
Rob W

Cảm ơn vì đã trả lời cướp của bạn. tôi đã sao chép các đoạn mã trong liên kết đính kèm của bạn nhưng nó vẫn không hoạt động. Vấn đề là tiện ích mở rộng của tôi là một cửa sổ bật lên và tôi chỉ cần lấy HTML khi người dùng mở tiện ích mở rộng của tôi. ví dụ: nếu tab hiện tại là facebook.com thì chỉ khi tôi mở tiện ích mở rộng của mình, tôi sẽ truy xuất nguồn html vào tệp js của mình (không phải tập lệnh nội dung hoặc trang nền).
Mr T.

Cập nhật câu hỏi của bạn với mã hiện tại của bạn. Mã phải chứa các nhận xét làm nổi bật vấn đề.
Rob W

Câu trả lời:


155

Chèn một tập lệnh vào trang mà bạn muốn lấy nguồn và thông báo nó trở lại cửa sổ bật lên ....

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 Rất tiếc vì bài đăng đầu tiên của tôi, tôi đã không chú ý đến các nhận xét (một lần nữa) và cuối cùng chỉ lặp lại những gì Rob W đã nói. Bài viết mới phải có những gì bạn muốn.
PAEz

Cảm ơn, câu trả lời của bạn thực sự hữu ích, vấn đề của tôi là onMessage trên xảy ra không đồng bộ. trong cửa sổ bật lên của tôi, tôi có tất cả các loại nội dung khác chuyển tiếp trên HTML nguồn. Làm cách nào để lưu nguồn trong var toàn cục và chỉ sau đó tiếp tục với chức năng tải trang?
Mr T.

Tôi không nghĩ bạn có thể. Bạn sẽ phải đặt nó trong mã gọi lại hoặc trong một hàm và gọi nó trong lệnh gọi lại ... nếu chỉ JS có một gotolệnh aye? ; P
PAEz

19
Tại sao không chỉ một cái gì đó như document.documentElement.outerHTML thay vì hàm DOMtoString?
djfm

@djfm Điều đó khá ổn mọi lúc. Chỉ là từ những gì tôi có thể nói rằng chức năng của Rob W đã hoàn thiện hơn ... trả về loại tài liệu, ví dụ như giải pháp của bạn thì không, bạn chỉ nhận được phần html.
PAEz

0

Đây là giải pháp của tôi:

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});' }
        );
    });
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.