我正在创建一个Chrome扩展程序,它将转到指定的网站,并从源代码中获取网站的部分HTML。 我希望将html内容包含在具有类名&span; rating1 rating-num-span'的div中。
我尝试使用.getElementsByClassName,但它返回undefined,但是当我在(' h2')上使用.getElementsByTagName时,它工作正常。
这是从我的main.js
发出请求的javascript函数function getFlowSite(){
var request = new XMLHttpRequest();
request.onreadystatechange = function(){
if (request.readyState == 4){
if (request.status == 200){
var temp = document.createElement('div');
temp.innerHTML = request.responseText;
alert(temp.getElementsByTagName('h2')[0].innerText);
alert(temp.getElementsByClassName('span1 rating-num-span')[0].innerText);
}
else{
console.log("Messed up!!!");
}
}
};
request.open("GET", "http://uwflow.com/course/" + courseName, true);
request.send(null);
}
...难倒 谢谢你的阅读!
--------------------更新------------------------
原来这个类最初没有出现在页面上,并且是用脚本动态加载的。加载完所有内容后如何获取页面的源代码?
答案 0 :(得分:1)
该元素由页面脚本动态添加。
它最初不在页面上。您可以通过检查来自网站的第一个服务器响应来检查这一点,当它加载devtools网络面板打开时。或者,如果你使用了很棒的uBlock(origin)扩展,只需暂时禁用网站上的所有javascript并重新加载页面。
您有两种选择:
了解该网页的代码如何从服务器/其他地方获取数据并自行完成,通常有某种JSON API。例如,在这种情况下,页面中有一个巨大的配置对象:
<script>
window.pageData.courseObj = {"ratings": [{"count": 375, "rating": .............
只需在.responseType = "document"
模式下使用XMLHttpRequest并获取该元素,然后在其上使用JSON.parse
。
或者,实际上,在这种情况下,一个简单的regexp + JSON.parse将执行:
var match = request.responseText
.match(/window\.pageData\.courseObj\s*=\s*(\{.+?\});\s*[\r\n]/);
var config = JSON.parse(match[1]);
config.ratings.forEach(function(r) { console.log(r) });
对象{计数:375,评级:0.6986666666666667,名称:“有用”}
对象{count:494,评级:0.7449392712550608,名称:“easiness”}
对象{计数:555,评级:0.5621621621621622,名称:“兴趣”}
上述代码未经过实时测试,不包含任何必须在实际代码中实施的错误检查。
将页面加载为普通浏览器标签而不激活它,注入内容脚本,等待元素出现,提取数据,关闭标签。
的manifest.json:
"permissions": ["http://uwflow.com/*"]
- 非活动标签上的executeScript权限
popup.js:
var globalTabId = 0;
function openTab(url) {
chrome.tabs.create({url: url, active: false}, function(tab) {
globalTabId = tab.id;
chrome.tabs.executeScript(tab.id, {file: "getData.js", runAt: "document_end"});
});
}
chrome.runtime.onMessage.addListener(function(msg, sender, response) {
if (msg.action == "data" && sender.tab && sender.tab.id == globalTabId) {
chrome.tabs.remove(globalTabId);
processData(msg.data);
}
});
getData.js ,这是一个内容脚本,但不需要在manifest.json中声明。
var interval = setInterval(function() {
var ratings = document.querySelector(".span1.rating-num-span");
if (!ratings) {
return;
}
clearInterval(interval);
chrome.runtime.sendMessage({action: "data", data: {ratings: ratings.textContent}});
}, 100);