XMLHttpRequest用动态内容获取DOM

时间:2013-10-11 22:20:27

标签: javascript ajax dom google-chrome-extension xmlhttprequest

我正在创建一个监控指定网站的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();
}

提前谢谢你,如果我的问题看似微不足道,那就很抱歉

1 个答案:

答案 0 :(得分:2)

详细说明我的意见:

  

如果您想要渲染动态部分,则需要在iframe中加载内容。

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

  

小心X-Frame-Options标题,

下一个解决方案仅在X-Frame-Options未与响应一起发送时才有效。设置此响应标头后,页面无法嵌入到框架中。您必须删除此标头,如this answer

中所示
  

并确保在iframe上设置sandbox属性以避免帧破坏。

您将在文档中插入包含此方内容的<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从生成元素的脚本中获取数据。