【问题标题】:Why does XPath exaluate gives snapshotLength = 1 for /html/body and 0 for /html/body/div[3]/div[3]/div/div[6]/div[2]/div/div/div?为什么 XPath exaluate 给 /html/body 的 snapshotLength = 1 和 /html/body/div[3]/div[3]/div/div[6]/div[2]/div/div/div 的 0?
【发布时间】:2017-12-27 04:01:51
【问题描述】:

你能告诉我为什么 XPath exaluate 给出了

  snapshotLength = 1 for /html/body 

和 0 代表

  /html/body/div[3]/div[3]/div/div[6]/div[2]/div/div/div

较长的 XPath 是真实的,由 Firepath 为该页面上的对象计算得出

http://srv1.yogh.io/#mine:height:0

我在 Greasemonkey 中运行以下脚本。

// ==UserScript==
// @name        xpath greasemonkey
// @namespace   bbb
// @description f
// @match       http://srv1.yogh.io/#mine:height:0
// @version     1
// @grant       none
// ==/UserScript==
var allLinks, thisLink;
console.log("dfsdsdsdfg");
allLinks = document.evaluate(
     "/html/body/div",
     document,
     null,
     XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
     null);
// for (var i = 0; i < allLinks.snapshotLength; i++) {
//   thisLink = allLinks.snapshotItem(i);
 // console.log("found");
// }
console.log(allLinks.snapshotLength)


// /html/body/div[3]/div[3]/div/div[6]/div[2]/div/div/div
// ---
// UPDATED userscript

// ==UserScript==
// @name        xpath greasemonkey2
// @namespace   bbb
// @description f
// @match       http://srv1.yogh.io/#mine:height:0
// @version     1
// @grant       none
// ==/UserScript==

window.setTimeout(function() {
  var allLinks, thisLink;
  console.log("dfsdsdsdfg");
   
  allLinks = document.evaluate(
       "/html/body/div[3]/div[3]/div/div[6]/div[2]/div/div/div",
       document,
       null,
       XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
       null);
  if(allLinks.snapshotLength) {
    console.log(allLinks.snapshotLength);
    console.log(allLinks.snapshotItem(0).innerHTML)
  } else {
    console.log("Bother...");
    console.log(allLinks.snapshotLength)
  }
}, 15000);

function myFunction() {
    if (window.top != window.self)  {
      alert("This window is not the topmost window! Am I in a frame?");
        document.getElementById("demo").innerHTML = "This window is not the topmost window! Am I in a frame?";
    } else { 
       alert("This window is the topmost window! Am I in a frame?");
        document.getElementById("demo").innerHTML = "This window is the topmost window!";
    } 
}
var input=document.createElement("input");
input.type="button";
input.value="GreaseMonkey Button";
input.onclick = myFunction;
document.body.appendChild(input); 

我想要代码在网页上找到 XPathed DIV 对象 突出显示它并通过 console.log 返回:

<div class="gwt-Label">2083236893</div>

用于后处理以通过以下方式读取字符串 2083236893 .innerText 或 .innerHTML

有任何想法或任何可在 GM 或 Fiddle 中工作的脚本演示吗?

【问题讨论】:

标签: xpath greasemonkey document.evaluate


【解决方案1】:

您的 XPath 实际上没问题,如果您直接在浏览器的控制台中输入它应该可以工作。问题是区块链网页的内容是由脚本动态生成的,所以在执行用户脚本时,您要查找的节点并不存在。

您需要延迟代码运行,直到页面完成加载。 @run-at userscript 元数据指令应该可以实现这一点,但是它在 GreaseMonkey v4 中被破坏了,或者区块链脚本运行时间太长,您需要将用户脚本延迟更长的时间。无论哪种方式,将代码包装在 setTimeout() 中都是一种简单的方法(检测其他脚本何时完成会更优雅):

// ==UserScript==
// @name        xpath greasemonkey
// @namespace   bbb
// @description f
// @match       http://srv1.yogh.io/
// @version     1
// @grant       none
// ==/UserScript==

window.setTimeout(function() {
  var allLinks, thisLink;
  console.log("dfsdsdsdfg");
  allLinks = document.evaluate(
       "/html/body/div[3]/div[3]/div/div[6]/div[2]/div/div/div",
       document,
       null,
       XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE,
       null);
  if(allLinks.snapshotLength) {
    console.log(allLinks.snapshotItem(0).innerHTML);
  } else {
    console.log("Bother...");
  }
}, 5000);

(请注意,我还必须更改您的 @match 指令以让 Greasemonkey 在正确的页面上运行脚本)。

【讨论】:

  • 感谢@JRI 的出色回答。我已经将您的脚本稍微修改为 console.log(allLinks.snapshotLength) ,因为我得到了 console.log("Bother...");每次执行。在超时增加到 15000 我得到 dfsdsdsdfg 13 dfsdsdsdfg Bother... 0 。看起来脚本被执行了两次。测试srv1.yogh.io/#mine:height:0 dfsdsdsdfg 2083236893 ...可下载字体:下载失败.. dfsdsdsdfg 麻烦... 0 看起来 allLinks.snapshotLength 从 1 修改为 0
  • 跟进您的脚本稍作修改,将更多 consol.log 的超时设置为 15000,并且脚本在 GM3.17 中执行两次,该脚本适用于 FirefoxESR 52.2.1 32 位。 dfsdsdsdfg xpath_greasemonkey2.user.js:12:3 1 xpath_greasemonkey2.user.js:21:5 2083236893 xpath_greasemonkey2.user.js:22:5 dfsdsdsdfg xpath_greasemonkey2.user.js:12:3 麻烦... xpath_greasemonkey2.user.js: 24:5 0 xpath_greasemonkey2.user.js:25:5 是什么让 GM 脚本被执行两次并且第二次 allLinks.snapshotLength 从 1 切换到 0?
  • 脚本在 GM4.1 或 Tampermonkey v4.4 中只为我运行一次。如果它运行两次,它可能在 IFrame 以及主网页上运行。主页面中的 snapshotLength 仅为 1,因为 IFrame 不会具有相同的结构。您可以通过测试 if (window.self !== window.top) 来检查这一点。
  • 我已经附加了 if (window.top != window.self) input.value="GreaseMonkey Button"; and else { alert("这个窗口是最上面的窗口!我在框架中吗?");关闭控制台并在按钮单击时获得上述消息。不知道为什么脚本代码会立即执行,而不是等待 15000 毫秒 window.setTimeout(function() { 我得到 allLinks = document.evaluate( 立即计算并且 Greasemonkey 按钮同时出现在顶部,而不是等待 15000。不知道如何延迟allLinks = document.evaluate(if window.setTimeout(function()
  • 顺便说一句,将更新的脚本附加到上面的 sn-p 以供您查看
猜你喜欢
  • 1970-01-01
  • 2022-01-10
  • 2016-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多