รับ HTML ต้นทางของหน้าปัจจุบันจากส่วนขยาย chrome


86

ฉันมีนามสกุลโครเมี่ยม ฉันต้องการวิเคราะห์จากซอร์ส 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 และได้รับแหล่งที่มา
Rob W

ขอบคุณสำหรับการตอบกลับของคุณปล้น ฉันคัดลอกส่วนของรหัสในลิงก์ที่แนบมาของคุณ แต่ยังใช้งานไม่ได้ ปัญหาคือส่วนขยายของฉันเป็นป๊อปอัปและฉันต้องการรับ HTML ก็ต่อเมื่อผู้ใช้เปิดส่วนขยายของฉัน ตัวอย่างเช่นหากแท็บปัจจุบันคือ facebook.com เมื่อฉันเปิดส่วนขยายเท่านั้นฉันจะดึงซอร์ส html ไปยังไฟล์ js ของฉัน (ไม่ใช่สคริปต์เนื้อหาหรือหน้าพื้นหลัง)
นายต.

อัปเดตคำถามของคุณด้วยรหัสปัจจุบันของคุณ รหัสต้องมีความคิดเห็นที่เน้นปัญหา
Rob W

คำตอบ:


157

ใส่สคริปต์ลงในหน้าที่คุณต้องการรับแหล่งที่มาและส่งข้อความกลับไปที่ป๊อปอัป ...

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 ขอโทษสำหรับโพสต์แรกของฉันไม่ได้ให้ความสำคัญกับความคิดเห็นมากพอ (อีกครั้ง) และจบลงด้วยการสำรอกสิ่งที่ Rob W พูด โพสต์ใหม่ควรมีสิ่งที่คุณต้องการ
PAEz

ขอบคุณคำตอบของคุณมีประโยชน์มากปัญหาของฉันคือ onMessage เกิดขึ้นแบบอะซิงโครนัส ในป๊อปอัปของฉันฉันมีสิ่งอื่น ๆ อีกมากมายที่ถ่ายทอดบน HTML ต้นทาง ฉันจะบันทึกซอร์สใน global var ได้อย่างไรจากนั้นดำเนินการต่อโดยใช้ฟังก์ชัน page onload
นายต.

ฉันไม่คิดว่าคุณจะทำได้ คุณจะต้องใส่ไว้ในรหัสการโทรกลับหรือในฟังก์ชันและเรียกสิ่งนั้นในการเรียกกลับ ... ถ้ามีเพียง JS เท่านั้นที่มีgotoคำสั่งใช่ไหม ; P
PAEz

21
ทำไมไม่เพียงบางอย่างเช่น document.documentElement.outerHTML แทนที่จะเป็นฟังก์ชัน DOMtoString?
djfm

@djfm นั่นคงจะดีตลอดเวลา จากสิ่งที่ฉันสามารถบอกได้ว่าฟังก์ชันของ Rob W นั้นสมบูรณ์ยิ่งขึ้น ... ส่งกลับประเภทหลักเช่นว่าโซลูชันของคุณไม่มีคุณได้รับเฉพาะส่วน html
PAEz

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.