page.hover() 无效

page.hover() having no effect

描述

我网站上的一些按钮在悬停时会改变颜色,但是当使用 时,它似乎没有任何效果。

相关代码:

import { puppeteer } from './deps.ts';

const browser = await puppeteer.launch();
const page = await browser.newPage();

const url = 'https://sweet-snake-49.deno.dev';
await page.goto(url);
await page.setViewport({
    width: 1600,
    height: 1200
});
await page.hover('#left');
await page.screenshot({ path: Deno.cwd() + '/example.png' }); 

await browser.close();

要重现的完整项目here

预期输出

悬停时,我希望颜色会变成带有框阴影的黄色,但不幸的是,好像没有悬停归因于我的按钮。

发件人:

收件人:

问题

如何让 page.hover() 在我的 #left 按钮上工作?

它似乎与 deno 无关,因为 nodejs 正在发生完全相同的问题

您应该等待该元素存在,然后尝试与在 DOM 中找到的元素进行交互。

使用 Puppeteer 页面 waitForSelector 的示例:

import { puppeteer } from './deps.ts';

const browser = await puppeteer.launch();
const page = await browser.newPage();

const url = 'https://sweet-snake-49.deno.dev';

await page.goto(url);
await page.setViewport({
    width: 1600,
    height: 1200
});

// wait for element before trying to hover
page.waitForSelector('#left').then(() =>
    await page.hover('#left');
    await page.screenshot({ path: Deno.cwd() + '/example.png' }); 
);

await browser.close();

我使用了一个 Docker 容器(因为我不喜欢使用 deno-puppeteer 要求的自由权限来禁用安全沙箱),所以我的配置与你的有点不同.

我已经修改了 Dockerfile template from the deno-puppeteer repo 和您的源文件,我在屏幕截图中获得了成功的悬停状态:

Note that the target page you linked to uses the glyph (U+25C0 BLACK LEFT-POINTING TRIANGLE) for the text inside the left button — and, it doesn't appear to render in the container: the screenshot shows a default box character in place of it. I suppose a compatible font would need to be installed as an additional step in the Dockerfile in order to address this: more debugging would be required.

为了让代码在 Stack Overflow 上可用(而不是依赖外部托管),我将内联复制目录中的文件内容(我将其命名为 so-70731163您问题的 ID),以及控制台 input/output:


./.vscode/settings.json

{
  "deno.enable": true,
  "deno.lint": true,
  "deno.unstable": true,
  "deno.config": "./src/deno.json"
}

./src/deno.json

{
  "compilerOptions": {
    "lib": [
      "deno.window",
      "dom",
      "dom.iterable"
    ]
  }
}

./src/deps.ts

export * as path from 'https://deno.land/std@0.122.0/path/mod.ts';
export {
  assert,
  assertExists,
} from 'https://deno.land/std@0.122.0/testing/asserts.ts';
export {
  default as puppeteer,
  type ElementHandle,
  type ScreenshotOptions,
} from 'https://deno.land/x/puppeteer@9.0.2/mod.ts';

./src/main.ts

import {
  assert,
  assertExists,
  path,
  puppeteer,
  type ElementHandle,
  type ScreenshotOptions,
} from './deps.ts';

// Create data directory if it doesn't already exist
const dataDir = path.resolve('container-data');
await Deno.mkdir(dataDir, {recursive: true});

// Browser launch options required for usage in Docker
// https://github.com/lucacasonato/deno-puppeteer/issues/16#issuecomment-842784232
// https://github.com/lucacasonato/deno-puppeteer/blob/9.0.2/examples/docker.js
const dockerLaunchArgs = [
  '--no-sandbox',
  '--disable-dev-shm-usage',
];

const browser = await puppeteer.launch({args: dockerLaunchArgs});
const page = await browser.newPage();
await page.setViewport({width: 1600, height: 1200});

const url = 'https://sweet-snake-49.deno.dev';
await page.goto(url);

// Get handle for left button (used in next step) and hover it
const leftBtnHandle = await page.$('button#left');
assertExists(leftBtnHandle);
await leftBtnHandle.hover();

// Get handle for controls container (for screenshot in next step)
const getControls = (leftBtn: HTMLButtonElement) => leftBtn.closest('section');
const controlsHandle =
  (await leftBtnHandle.evaluateHandle<ElementHandle>(getControls)).asElement();
assertExists(controlsHandle);

// Instead of using Puppeteer API to save screenshot,
// get raw buffer data for more control
const screenshotOpts: ScreenshotOptions = {encoding: 'binary', type: 'png'};
const pngData = await controlsHandle.screenshot(screenshotOpts);
assert(pngData instanceof Uint8Array);
const screenshotPath = path.join(dataDir, 'controls.png');
await Deno.writeFile(screenshotPath, pngData);

await browser.close();

./docker-build

docker build --tag so-70731163 .

./docker-run

docker run -it \
  --rm \
  --name so-70731163 \
  --mount type=bind,source="$(pwd)",destination=/app \
  so-70731163

./Dockerfile

FROM debian:buster-slim

ENV DENO_VERSION=1.18.0
ARG DEBIAN_FRONTEND=noninteractive

RUN apt-get -qq update \
    && apt-get -qq install -y --no-install-recommends \
    curl \
    ca-certificates \
    unzip \
# ↓ https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix
# Since I want to leave the contents of troubleshooting.md as it is, ca-certificates is intentionally duplicated here.
    ca-certificates \
    fonts-liberation \
    libappindicator3-1 \
    libasound2 \
    libatk-bridge2.0-0 \
    libatk1.0-0 \
    libc6 \
    libcairo2 \
    libcups2 \
    libdbus-1-3 \
    libexpat1 \
    libfontconfig1 \
    libgbm1 \
    libgcc1 \
    libglib2.0-0 \
    libgtk-3-0 \
    libnspr4 \
    libnss3 \
    libpango-1.0-0 \
    libpangocairo-1.0-0 \
    libstdc++6 \
    libx11-6 \
    libx11-xcb1 \
    libxcb1 \
    libxcomposite1 \
    libxcursor1 \
    libxdamage1 \
    libxext6 \
    libxfixes3 \
    libxi6 \
    libxrandr2 \
    libxrender1 \
    libxss1 \
    libxtst6 \
    lsb-release \
    wget \
    xdg-utils \
# ↑ https://github.com/puppeteer/puppeteer/blob/main/docs/troubleshooting.md#chrome-headless-doesnt-launch-on-unix
# ↓ Added based on the information obtained from by console.log(line) at https://deno.land/x/puppeteer@9.0.2/src/deno/BrowserRunner.ts#L168.
    libdrm2 \
    libxkbcommon0 \
    libxshmfence1 \
# ↑ Added based on the information obtained from by console.log(line) at https://deno.land/x/puppeteer@9.0.2/src/deno/BrowserRunner.ts#L168.
    && curl -fsSL https://github.com/denoland/deno/releases/download/v${DENO_VERSION}/deno-x86_64-unknown-linux-gnu.zip \
    --output deno.zip \
    && unzip deno.zip \
    && rm deno.zip \
    && chmod 755 deno \
    && mv deno /usr/bin/deno \
    && apt-get -qq remove --purge -y \
    curl \
# Do not remove ca-certificates as it is required by puppeteer.
#    ca-certificates \
    unzip \
    && apt-get -y -qq autoremove \
    && apt-get -qq clean \
    && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*

RUN useradd --uid 1993 --user-group deno \
 && mkdir /deno-dir/ \
 && chown deno:deno /deno-dir/

ENV DENO_DIR /deno-dir/

# --- PLACE CUSTOM COMMANDS BELOW --- #

WORKDIR /app
# Bind CWD instead of copying
# COPY . .

# https://deno.land/x/puppeteer@9.0.2#installation
# In your real script, replace the installation script with https://deno.land/x/puppeteer@9.0.2/install.ts
RUN PUPPETEER_PRODUCT=chrome deno run -A --unstable https://deno.land/x/puppeteer@9.0.2/install.ts

ENTRYPOINT ["deno"]
CMD ["run", "-A", "--no-check", "--unstable", "./src/main.ts"]


在控制台中:

so-70731163 % ./docker-build
# Lots of Docker build output messages...

so-70731163 % ./docker-run
# Lines showing compilation info: Download moduleURL...

之后,上面的截图被写入./container-data/controls.png

要删除内置的 docker 图像:

docker image rm so-70731163