1

我正在创建一个监控给定网站的 chrome 扩展。我正在使用 XMLHttpRequest 来获取该站点的 DOM,然后对其进行解析并获取所需的数据。

问题是 XMLHttpRequest 不返回带有动态内容(例如图像、动态文本等)的完全加载的 DOM。

我用谷歌搜索了这个问题,似乎没有解决办法,但我可能不正确。

XHR 有没有办法返回完全加载的 DOM。

这是我的代码

window.onload = function () { chrome.runtime.sendMessage({points: document.getElementsByClassName('notification-count hidden')[1].outerText}); } //Works fine, but I need the same result with XHR

function getPoints()
{
    var link = 'example'; //placeholder

    var xhr = new XMLHttpRequest();
    xhr.open('GET', link, true);
    xhr.responseType = 'text';
    xhr.onload = function(e) {
    if (xhr.readyState== 4 && xhr.status == 200) 
    {
        DOM = xhr.response;
        console.log(DOM); //Returns the DOM of the site but missing dynamic content
    }
};

xhr.send();
}

提前谢谢你,如果我的问题看起来微不足道,对不起

4

1 回答 1

2

详细说明我的评论:

如果要呈现动态部分,则需要在 iframe 中加载内容。

这是必要的,因为XMLHttpRequest只是获取页面的源代码,它不运行任何嵌入的脚本。

注意 X-Frame-Options 标头,

下一个解决方案仅在X-Frame-Options未随响应发送时才有效。设置此响应标头时,页面不能嵌入到框架中。您必须删除此标头,如本答案所示。

并确保您在 iframe 上设置了沙盒属性以避免框架破坏。

您将在文档中插入一个<iframe>包含本方内容的内容。在没有任何反制措施的情况下,这个第三方页面可以使用 替换顶部文档if (top !== window) {top.location = location.href;},也称为框架破坏。

从外观上看,您的脚本被用作内容脚本。插入一个框架,并在该框架内使用相同的内容脚本来获取所需的信息。

manifest.json

...
"content_scripts": [{
    "js": ["contentscript.js"],
    "all_frames": true,
    "matches": ["*://*.example.com/*"]
}],
...

contentscript.js

function getPoints() {
    var iframe = document.createElement('iframe');
    iframe.src = 'http://www.example.com/';
    // Remove iframe when the content has (not) loaded
    iframe.onerror =
    iframe.onload = function() {
        setTimeout(function() {
            iframe.parentNode.removeChild(iframe);
        }, 5000);
    };
    // Put security restrictions on the iframe
    iframe.sandbox = 'allow-scripts';
    // Make frame invisible
    iframe.style.height = '1px';
    iframe.style.width = '1px';
    iframe.style.position = 'fixed';
    iframe.style.top = '-9px';
    iframe.style.left = '-9px';
    // Insert iframe in the document, and load its content
    document.body.appendChild(iframe);
}
function sendPoints(attempts) {
    var points = document.getElementsByClassName('notification-count hidden');
    if (points.length > 1) { // <-- Example, based on your question
        // Desired element found, send the message to the background page
        chrome.runtime.sendMessage({
            points: points[1].textContent
        });
    } else if (--attempts > 0) {
        // Element not found, and some attempts left. Try again soon.
        setTimeout(sendPoints, 250, attempts);
    }
}
sendPoints(40);

这种方法有一个巨大的延迟:首先需要加载页面,然后加载和解析所有脚本和资源。如果可能,尝试用其他方法提取“动态”信息。尝试对您正在抓取的页面进行反向工程,并尝试通过其他方式获得所需的值,例如通过使用XMLHttpRequest从生成元素的脚本中获取数据。

于 2013-10-12T10:32:05.780 回答