我正在创建一个监控指定网站的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();
}
提前谢谢你,如果我的问题看似微不足道,那就很抱歉
答案 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
从生成元素的脚本中获取数据。