我正在制作一个网页阅读器,它需要在文档开始阅读时清点文档中的文本节点,因为它会读取页面中的每个句子。所以我正在“抓取”你可以说的文本节点。
我有一个使用document.createTreeWalker
来获取文本节点清单的过程。
我还没有弄清楚这个模式(我认为有一个),但是当我使用document.body
时,指向的文档不是主页面,而是iframe的文档。在我目前的调试中,这恰好是一个推特小部件,但我想它可能是任何东西。这不是一个推特问题,但是如果您碰巧知道Twitter正在做一些非常普通的事情,那么您可以让它通知您的答案,使文档始终转到它而不是顶级文档。无论如何,无论来源如何,我都需要获得正确的文件。
你问我,正确的文件是什么意思?我会说托管所选文本的文档,或者如果没有选择文本则是顶级文档。
但我真正的问题是这是怎么发生的,为什么会这样呢?我最后一次搞砸dom是在2009年,当时我在IE中写了一个网页阅读器。时代变了;我正在撰写Chrome扩展程序,这些天网页似乎要复杂1000倍。老实说,它就像平均网页上的马戏团,大部分你都看不到;它被埋在地下,潜伏着像我的读者一样绊倒任何机器人。
我不想为twitter或任何其他小部件制作硬编码规则。必须有一千个这样的东西最终可以添加/注入页面。我实际上无法进入自定义规则的业务。
this.LoadAllTextNodes = function () {
this.AllTextNodes = textNodesUnder(document.body); // at some point, this document starts referring to something other than the top document. How did the definition of "document" change?
}
function textNodesUnder(root) {
var textNodes = [];
if (root.nodeType == 3)
textNodes.push(root);
else {
var treeWalker = document.createTreeWalker(root, NodeFilter.SHOW_TEXT, getTextElements, false);
var node;
while (node = treeWalker.nextNode())
textNodes.push(node);
}
return textNodes; // Array
}
function getTextElements(node) {
if (['SCRIPT', 'STYLE'].indexOf(node.parentNode.tagName) !== 0 && node.nodeValue !== '') //filter out script elements and empty elements
return NodeFilter.FILTER_ACCEPT
else
return NodeFilter.FILTER_SKIP
}
我正在测试的网页恰好是builder doc。页面主题涉及Chrome调试的事实只是巧合。它与这个问题无关。我只是在你希望看到页面来源的情况下添加它。
https://code.visualstudio.com/blogs/2016/02/23/introducing-chrome-debugger-for-vs-code
<iframe id="twitter-widget-0" scrolling="no" frameborder="0" allowtransparency="true" class="twitter-follow-button twitter-follow-button-rendered" title="Twitter Follow Button" src="https://platform.twitter.com/widgets/follow_button.d59f1863bc12f58215682d9908af95aa.en.html#dnt=false&id=twitter-widget-0&lang=en&screen_name=code&show_count=true&show_screen_name=true&size=m&time=1474137195557" style="position: static; visibility: visible; width: 191px; height: 20px;" data-screen-name="code"></iframe>
答案 0 :(得分:1)
在Chrome扩展程序中,内容脚本会针对每个窗口运行,包括顶部窗口和所有iframe。通过这种方式,Chrome扩展程序访问优先于脚本标记中运行的脚本可能具有的跨站点限制。
这是为每个框架实例化一个上下文,它将在该框架中运行的扩展代码的重复指向它们各自的文档,而不是顶部窗口的文档。
它并行运行代码。在我的情况下,每个框架都会排队要在不知情的情况下阅读内容,以便单身window.speechSynthesis
阅读。
修复很简单;只是不要在非顶级窗口中运行:
if (window != window.top) return; // don't run in frames