Geçerli sayfanın kaynak HTML'sini chrome uzantısından alma


85

Bir krom uzantım var. Mevcut sayfanın HTML kaynağından analiz etmem gerekiyor. Burada arka plan sayfaları ve içerik komut dosyaları ile her türlü çözümü buldum ama hiçbiri bana yardımcı olmadı. şu ana kadar sahip olduğum şey:
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);
    }
});

Uyarı her zaman tanımsız olarak uyarı verir. content.js dosyasında geri arama işlevini şu şekilde değiştirsem bile:

callback('hello'); 

hala aynı sonuç. Neyi yanlış yapıyorum? belki ben buna yanlış yöne gidiyorum. gerçekten ihtiyacım olan şey bu. Kullanıcı uzantı açılır penceresini açtığında (ve ancak o zaman), analiz edebilmem için geçerli sayfanın HTML koduna ihtiyacım var. herhangi bir öneri?


Bir problem, arka plan sayfanızdaki kodun hemen çalıştırılmasıdır (içerik komut dosyaları enjekte edilmeden önce). Daha önce çok benzer / yinelenen bir soru sorulmuştu; Yeni bir Google Chrome sekmesi açın sayfasındaki yanıta bir göz atın ve kaynağı alın .
Rob W

Cevabınız için teşekkürler rob. ekli bağlantınızdaki kod bölümlerini kopyaladım ama hala çalışmıyor. Sorun, uzantımın bir açılır pencere olması ve HTML'yi yalnızca kullanıcı uzantımı açtığında almam gerekiyor. örneğin, geçerli sekme facebook.com ise, yalnızca uzantımı açtığımda, html kaynağını js dosyama (içerik betiğine veya arka plan sayfasına değil) alacağım.
Bay T.

Sorunuzu mevcut kodunuzla güncelleyin. Kod, sorunu vurgulayan yorumlar içermelidir.
Rob W

Yanıtlar:


156

Kaynağı almak istediğiniz sayfaya bir komut dosyası enjekte edin ve açılır pencereye geri mesaj gönderin ...

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 İlk yazım için çok üzgünüm, yorumlara yeterince dikkat etmedim (yine) ve Rob W'nun söylediklerini tekrar tekrar ortaya çıkardı. Yeni gönderi istediğinizi almalı
PAEz

Teşekkürler, cevabınız gerçekten yardımcı oldu, benim sorunum onMessage'ın eşzamansız gerçekleşmesidir. pop-up'ımda, kaynak HTML'de geçiş yapan her türlü başka şey var. kaynağı genel bir değişkene nasıl kaydedebilirim ve ancak bundan sonra sayfa yükleme işlevine nasıl devam edebilirim?
Bay T.

Yapabileceğini sanmıyorum. Ya onu geri arama koduna ya da bir işleve koyup geri aramada çağırmak zorunda kalacaksın ... eğer sadece JS'nin bir gotokomutu olsa evet? ; P
PAEz

21
Neden DOMtoString işlevi yerine document.documentElement.outerHTML gibi bir şey değil?
djfm

@djfm Bu hemen hemen her zaman iyi olurdu. Sadece Rob W'nun fonksiyonunun daha eksiksiz olduğunu söyleyebildiğim kadarıyla ... doctype döndürüyor, örneğin çözümünüz değil, sizinki yalnızca html kısmını alıyor.
PAEz

0

İşte benim çözümüm:

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});' }
        );
    });
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.