Windows 上的 Puppeteer:在按下 Meta 键时单击锚点不会按预期在新选项卡中打开 link
Puppeteer on Windows: Clicking anchor while Meta key pressed won't open link in new tab as expected
objective 是通过仅将鼠标移动到锚点并在当前鼠标光标位置发出单击(希望在 link 的可单击区域)来单击锚点,连同按下的 Meta 键(Mac OS 上的命令,Windows 上的 Ctrl)。
预期结果是 Chrome 打开一个新选项卡,加载 linked 页面。这在 Mac OS 上非常有效。但是在 Windows 上,它只是加载当前选项卡中的页面,就好像在单击期间没有按住 Ctrl 一样。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false,
executablePath: process.platform === "darwin" ?
"/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
// Location of Chrome for Windows Canary v76.x on my Windows system, yours may vary
: "C:\Users\ADMINI~1\AppData\Local\Google\CHROME~2\APPLIC~1\chrome.exe"
});
const page = await browser.newPage();
await page.goto("https://example.com", { waitUntil: 'networkidle0', timeout: 30000 });
let mySelector = "a";
let myElems = await page.evaluate(function(myThis) {
const domElemA = Array.from(document.querySelectorAll(myThis.selector));
const outElemA = domElemA.reduce(function(acc, cur) {
let r = cur.getBoundingClientRect();
let myObj = { rectLeft: Math.round(r.left), rectTop: Math.round(r.top), rectRight: Math.round(r.right), rectBottom: Math.round(r.bottom) };
// optionally do some filtering here, for objects outside the viewport.
// I know I could use Array.map() here if no filtering desired.
return [...acc, myObj];
}, []);
return outElemA;
}, { selector: mySelector });
console.log(myElems); // output the anchors we found
let e = myElems[0];
// determine the center of the anchor element
let x = Math.round((e.rectRight - e.rectLeft) / 2 + e.rectLeft);
let y = Math.round((e.rectBottom - e.rectTop) / 2 + e.rectTop);
let k = "Meta" // Command on MacOS, Ctrl on Windows
await page.mouse.move(x, y);
await page.waitFor(100);
await page.keyboard.down(k);
await page.waitFor(100);
await page.mouse.down();
await page.waitFor(100);
await page.mouse.up();
await page.waitFor(100);
await page.keyboard.up(k);
// Expected result: Link is opened in new tab due to Meta key held down while clicking
// Actual result on Mac OS: Behaves as expected
// Actual result on Windows: Opens link in the same tab, as if no Meta key were pressed
})();
人偶操纵者版本:
> npm view puppeteer
puppeteer@1.17.0 | Apache-2.0 | deps: 8 | versions: 642
Chrome Windows (Canary) 上的版本:
76.0.3803.0 (Official Build) (64-bit)
我知道有方便的 Puppeteer 函数,例如 page.click() 可以直接点击给定元素的中心,但任何此类快捷方式解决方案都超出了这个问题的范围。
它必须在不直接 select 元素的情况下工作,方法是将光标移动到可能的可点击区域,然后发出鼠标点击。我知道这种可点击的形状可能会有所不同,因此这种方法可能会失败——也不是我要求的那种建议 ("Why would you want to do that!?")。
此外,这不是经常听到的抱怨的重复,即 Meta+A(select 全部)在 Windows 上工作正常但在 [=50= 上没有按预期工作] OS。
但我确实怀疑这是一个类似的问题,但反过来,取决于处理 GUI 事件的位置,在 DOM 模型级别,在浏览器级别,在 OS等级.
如果问题是不可修复的,是否有解决方法可以在新选项卡中打开 link 但 100% 基于当前鼠标位置,而不做任何事情 "to" 直接定位 DOM 元素? Page.click() 等做了很多我不希望我的 "user" 做的 "stuff"。
这可能是因为 meta
键会引用 Windows 上的 "Windows" 键。
如果 windows 上的 运行 可以使用 ctrl
:
let k = process.platform == "win32" ? "Control" : "Meta";
https://nodejs.org/api/process.html#process_process_platform
objective 是通过仅将鼠标移动到锚点并在当前鼠标光标位置发出单击(希望在 link 的可单击区域)来单击锚点,连同按下的 Meta 键(Mac OS 上的命令,Windows 上的 Ctrl)。
预期结果是 Chrome 打开一个新选项卡,加载 linked 页面。这在 Mac OS 上非常有效。但是在 Windows 上,它只是加载当前选项卡中的页面,就好像在单击期间没有按住 Ctrl 一样。
const puppeteer = require('puppeteer');
(async () => {
const browser = await puppeteer.launch({
headless: false,
executablePath: process.platform === "darwin" ?
"/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome"
// Location of Chrome for Windows Canary v76.x on my Windows system, yours may vary
: "C:\Users\ADMINI~1\AppData\Local\Google\CHROME~2\APPLIC~1\chrome.exe"
});
const page = await browser.newPage();
await page.goto("https://example.com", { waitUntil: 'networkidle0', timeout: 30000 });
let mySelector = "a";
let myElems = await page.evaluate(function(myThis) {
const domElemA = Array.from(document.querySelectorAll(myThis.selector));
const outElemA = domElemA.reduce(function(acc, cur) {
let r = cur.getBoundingClientRect();
let myObj = { rectLeft: Math.round(r.left), rectTop: Math.round(r.top), rectRight: Math.round(r.right), rectBottom: Math.round(r.bottom) };
// optionally do some filtering here, for objects outside the viewport.
// I know I could use Array.map() here if no filtering desired.
return [...acc, myObj];
}, []);
return outElemA;
}, { selector: mySelector });
console.log(myElems); // output the anchors we found
let e = myElems[0];
// determine the center of the anchor element
let x = Math.round((e.rectRight - e.rectLeft) / 2 + e.rectLeft);
let y = Math.round((e.rectBottom - e.rectTop) / 2 + e.rectTop);
let k = "Meta" // Command on MacOS, Ctrl on Windows
await page.mouse.move(x, y);
await page.waitFor(100);
await page.keyboard.down(k);
await page.waitFor(100);
await page.mouse.down();
await page.waitFor(100);
await page.mouse.up();
await page.waitFor(100);
await page.keyboard.up(k);
// Expected result: Link is opened in new tab due to Meta key held down while clicking
// Actual result on Mac OS: Behaves as expected
// Actual result on Windows: Opens link in the same tab, as if no Meta key were pressed
})();
人偶操纵者版本:
> npm view puppeteer
puppeteer@1.17.0 | Apache-2.0 | deps: 8 | versions: 642
Chrome Windows (Canary) 上的版本:
76.0.3803.0 (Official Build) (64-bit)
我知道有方便的 Puppeteer 函数,例如 page.click() 可以直接点击给定元素的中心,但任何此类快捷方式解决方案都超出了这个问题的范围。
它必须在不直接 select 元素的情况下工作,方法是将光标移动到可能的可点击区域,然后发出鼠标点击。我知道这种可点击的形状可能会有所不同,因此这种方法可能会失败——也不是我要求的那种建议 ("Why would you want to do that!?")。
此外,这不是经常听到的抱怨的重复,即 Meta+A(select 全部)在 Windows 上工作正常但在 [=50= 上没有按预期工作] OS。
但我确实怀疑这是一个类似的问题,但反过来,取决于处理 GUI 事件的位置,在 DOM 模型级别,在浏览器级别,在 OS等级.
如果问题是不可修复的,是否有解决方法可以在新选项卡中打开 link 但 100% 基于当前鼠标位置,而不做任何事情 "to" 直接定位 DOM 元素? Page.click() 等做了很多我不希望我的 "user" 做的 "stuff"。
这可能是因为 meta
键会引用 Windows 上的 "Windows" 键。
如果 windows 上的 运行 可以使用 ctrl
:
let k = process.platform == "win32" ? "Control" : "Meta";
https://nodejs.org/api/process.html#process_process_platform