You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Chrome扩展无法获取网页window.scrollY值的问题求助

问题

我在用JS编写Chrome扩展抓取网页数据,目标网站是https://tellonym.me/tells,需要获取window.scrollY属性,但直接调用它始终返回0。我试了一种方法能在控制台打印正确值,但没法返回结果,没法实际使用:

function getScrollY() {
  var actualCode = 'console.log(window.scrollY)';

  document.documentElement.setAttribute('onreset', actualCode);
  document.documentElement.dispatchEvent(new CustomEvent('reset'));
  document.documentElement.removeAttribute('onreset');
}

我的内容脚本TellScrape.js里打印window.scrollY一直是0,但控制台其他输出能看到scrollY是非零值。以下是用到该属性的代码片段:

async function startScraping() {
  // Keep track of the span elements we've already added
  const spanElementsProcessed = new Set();

  const spanTexts = [];

  var textCountElement = document.createElement("p");
  textCountElement.style.fontSize = "15px";
  textCountElement.style.color = "gray";
  textCountElement.whiteSpace = "pre";
  countElement.appendChild(textCountElement);

  //this is where the "0" is coming from in the screenshot
  console.log(window.scrollY);

  // Keep scrolling until we reach the top of the page
  while (window.scrollY) {
    await new Promise(setTimeout);
    // Find all divs
    var divs = document.querySelectorAll("div");
    textCountElement.textContent = "Current scroll: " + window.scrollY + "\r\nCurrent scraped: " + spanTexts.length + "\r\nCurrent unique: " + [...new Set(spanTexts)].length;
    //these console.logs will eventually be removed but are here for debugging
    console.log("Current scroll: " + window.scrollY);
    console.log("Current scraped: " + spanTexts.length);
    console.log("Current unique: " + [...new Set(spanTexts)].length);

    // Check for any "show more" divs and expand them
    for (var div of divs) {
      if (div.textContent === 'show more') {
        div.click();
      }
    }

    // Get all span elements on the page
    var spans = document.querySelectorAll("span");

    // Loop through the elements and replace newline characters with ¶
    for (var i = 0; i < spans.length; i++) {
      var spanE = spans[i];
      spanE.textContent = spanE.textContent.replace(/\n/g, "¶");
    }

    // Now find all the span elements
    const spanElements = document.querySelectorAll('span');

    // Add every new span element's textcontent into spanTexts
    for (const span of spanElements) {
      if (!spanElementsProcessed.has(span)) {
        spanElementsProcessed.add(span);
        spanTexts.push(span.textContent);
      }
    }
    // Wait 100 milliseconds before continuing the loop
    await sleep(100);
  }

解决建议

1. 用chrome.scripting.executeScript获取真实scrollY

内容脚本和页面主执行上下文相互隔离,直接访问window.scrollY拿到的是内容脚本上下文的数值,而非页面真实滚动值。通过Chrome脚本API注入代码到页面主上下文,就能获取正确值并返回:

async function getRealScrollY() {
  // 若在内容脚本中,可通过chrome.tabs.getCurrent获取当前tabId
  const currentTab = await chrome.tabs.getCurrent();
  const result = await chrome.scripting.executeScript({
    target: { tabId: currentTab.id },
    func: () => window.scrollY, // 在页面主上下文执行并返回scrollY
  });
  return result[0].result;
}

调用时替换原代码中的window.scrollY为await getRealScrollY()即可,注意要在async函数内使用。

2. 定位页面内滚动容器,取其scrollTop属性

很多现代网站不会直接使用window滚动,而是将内容放在带overflow: auto/scroll的容器内实现内部滚动。你可以检查页面DOM结构,找到实际承载滚动内容的容器,获取它的scrollTop:

// 根据页面实际DOM结构调整选择器,比如找带特定类名的容器
const scrollContainer = document.querySelector('div[class*="scroll-content"]');
const currentScroll = scrollContainer ? scrollContainer.scrollTop : window.scrollY;

如果不确定容器,也可以遍历所有带有overflow属性的元素,检查哪个的scrollTop不为0。

3. 改造原有事件触发方法,通过自定义事件传值

你原来的方法能打印正确值,说明代码已在页面主上下文执行,可修改为通过自定义事件将值传回内容脚本:

function getScrollY() {
  return new Promise(resolve => {
    // 监听自定义事件接收返回值
    window.addEventListener('scrollYResult', function receiveResult(e) {
      resolve(e.detail);
      window.removeEventListener('scrollYResult', receiveResult); // 移除监听避免重复触发
    });

    // 注入代码到页面主上下文,获取scrollY后触发事件传递
    const actualCode = `
      const scrollVal = window.scrollY;
      window.dispatchEvent(new CustomEvent('scrollYResult', { detail: scrollVal }));
    `;
    document.documentElement.setAttribute('onreset', actualCode);
    document.documentElement.dispatchEvent(new CustomEvent('reset'));
    document.documentElement.removeAttribute('onreset');
  });
}

调用时用const scrollY = await getScrollY();即可拿到正确值。

4. 调整循环逻辑,不依赖scrollY判断是否到顶

如果上述方法都有问题,可换个思路:记录上次滚动位置,当连续几次位置不变时,判定已滚动到顶部:

let lastScrollPos = -1;
let noChangeCount = 0;

// 连续3次滚动位置不变则停止循环
while (noChangeCount < 3) {
  const currentScroll = await getRealScrollY(); // 用上述方法获取真实滚动值
  if (currentScroll === lastScrollPos) {
    noChangeCount++;
  } else {
    noChangeCount = 0;
    lastScrollPos = currentScroll;
  }

  // 你的原有业务代码...

  await sleep(100);
}

内容的提问来源于stack exchange,提问作者Novet

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 10:36:08