Puppeteer是一个Node库,它提供了一个高级API,通过DevTools协议控制无头Chrome或Chromium。它还可以配置为使用完整(非无头)Chrome或Chromium。
我有一个使用 Jest 运行的测试套件。我想在任何失败的测试后触发挂钩,理想情况下测试上下文仍然可用。 具体来说,我通过 jest-pup 使用 Puppeteer...
在本地 Windows 中配置 Puppeteer 可执行文件路径 chrome
木偶师版本:1.11.0 平台/操作系统版本:Windows 10 pro Node.js 版本:12.6.6 当我在windows中进行本地开发测试时,发生了executablePath的问题。 “启动失败...
我有一个值会变化的字符串,我需要将此字符串放入输入字段中。 (异步()=> { 让页数 = 1004327; 让浏览器 = 等待 puppeteer.launch({ 无头:真实, ...
目前我有一个网站,其 HTML 中有此内容。 我通过检查chrome开发者工具中的元素确认了这一点。 目前我有一个网站,其 HTML 中有此内容。 我通过检查chrome开发者工具中的元素确认了这一点。 <div class="hdp-photo-carousel" style="transform: translateX(0px);"> <div class="photo-tile photo-tile-large"> 我目视查看页面打开,可以看到该项目在那里。 然后 30 秒后我收到此错误: UnhandledPromiseRejectionWarning: TimeoutError: waiting for selector ".photo-tile" failed: timeout 30000ms exceeded 我在 puppeteer js 中的代码是: const pptrFirefox = require('puppeteer-firefox'); (async () => { const browser = await pptrFirefox.launch({headless: false}); const page = await browser.newPage(); await page.goto('https://zillow.com'); await page.type('.react-autosuggest__input', '8002 Blandwood Rd. Downey, CA 90240'); await page.click('.zsg-search-button_primary'); await page.waitForSelector('.photo-tile'); console.log('did I get this far?'); })(); 谁能告诉我我做错了什么? 每次页面内容更新时都需要添加page.waitForNavigation()。 (async () => { const browser = await pptrFirefox.launch({headless: false}); const page = await browser.newPage(); const navigationPromise = page.waitForNavigation({waitUntil: "domcontentloaded"}); await page.goto('https://zillow.com'); await navigationPromise; await page.type('.react-autosuggest__input', '8002 Blandwood Rd. Downey, CA 0240'); await page.click('.zsg-search-button_primary'); await navigationPromise; await page.waitForSelector('.photo-tile'); console.log('did I get this far?'); })(); 自提出此问题以来,该网站在 4 年内发生了变化,但这是一个常见的故事:手动验证某个元素是否存在于开发工具中,并将选择器复制到 Puppeteer,但等待时超时。 至少有一些常见原因: 该元素位于影子根中 该元素位于 iframe 中 元素需要滚动到视图中,否则会超出视口 服务器将您的脚本检测为机器人并阻止您,或呈现验证码 一种调试策略是全神贯注地运行(OP 已经这样做了,但未来的访问者可能不会这样做)。如果代码有效,那么该网站只会在您无头时将您检测为机器人。请参阅规范的 Why does headless need to false for Puppeteer to work? 了解后续步骤。 console.log(await page.content()) 可以帮助确定您是否被无头屏蔽。 如果拼命跑还是不行,查看页面看看原因。在某些情况下,页面可能会显示验证码,从而导致使用 puppeteer 通过 Headless Chrome 绕过验证码。在撰写本文时,当前问题似乎就是这种情况。 通常,添加更多 waitForNavigation 并将超时设置为 0 没有帮助(除非您通过单击或表单提交在页面之间导航,那么 waitForNavigation 可能是合适的)。 披露:我是链接博客文章的作者。
出于性能和资源原因,我尝试重用木偶浏览器和页面的同一实例。我的代码结构如下: 异步函数 createBrowser(id) { 让长凳=新达...
我正在尝试捕获页面上每个用户的用户名。我已经为 itemArea 变量尝试了大约 5 种不同的 CSS 选择器输入。我想我对 css 或 html 的经验还不够...... 如果
如何让 Puppeteer 仅单击具有设置“状态”的选择器?
我正在尝试制作一个机器人来帮助我买票,但是如图所示,只有几个座位。 我有一个问题要解决如何让 Puppeteer 仅单击可用的座位。 在
puppeteer - 如何从具有相同类的多个 div 的页面中提取内容
我有一个简单的木偶脚本来抓取公告网站。我需要获取页面的内容,在检查 DOM 之后,我可以看到所有内容都将具有相同的类...
const puppeteer = require("puppeteer"); const Cheerio = require("cheerio"); const url =“https://www.airbnb.co.in/s/Haridwar--Uttarakhand/homes?tab_id=home_tab&
使用 Puppeteer 和 Cheerio 抓取带有图像的卡片列表时丢失数据
我正在尝试刮一页卡片项目。我想从这些卡片中提取标题、价格、图像来源和其他属性。然而,当我用 Puppeteer 和 Cheerio 进行刮擦时,有些...
Puppeteer PDF-下载在下载的文件中显示 Chrome 工具栏
我正在尝试使用 puppeteer 下载 PDF 文件,但每次 Google Chrome 工具栏出现时,即使我使用纯 PDF 下载链接。 我尝试使用此代码下载 PDF: 公共...
我有一个 puppeteer 脚本,它循环遍历一组 URL,这些 URL 被导航到,然后从一些文本中抓取。但是,根据我当前的设置,循环在第一次迭代后停止。 我的...
Express Router API 中带有 Cheerio 的 Puppeteer-cluster 返回空响应
我正在使用express、puppeteer-cluster和cheerio编写一个API,它返回包含一个或多个可以作为查询参数添加的单词的所有锚元素。我想按顺序使用 puppeteer ...
无法在 Puppeteer js 中单击 href 或转到新页面
我正在尝试单击 puppeteer js 中的 href。 这是我的代码: 等待 page.goto('https://example.net/search/images?search=real+estate+postcards'); 等待 page.waitForSelector(".GridItem-it...
puppeteer 中的 page.$$(selector) 和 page.$$eval(selector, function) 有什么区别?
我正在尝试将页面元素加载到数组中并从两者中检索innerHTML并能够单击它们。 var scrapElements = 等待页面。$$(选择器); 等待grabElements[0].click(); 这...
嘿,我一直在尝试将socks5代理连接到puppeteer,但它给我抛出了这个错误“不支持代理”..抱歉我使用电话来提问, 我会发送屏幕截图和代码......
我正在尝试制作一个个人项目,该项目将使用刮刀从维基百科收集文本和数字数据,稍后将所有这些数据移动到数据库,然后比较所有这些收集到的值...
我正在尝试使用 puppeteer 从多个页面抓取价格。我遇到的问题是用所有抓取的数据编写一个 JSON 文件。问题是,如果我尝试写入文件
使用 waitForSelector 方法在 Puppteer JS 中更改类名时获取元素
我需要等待元素更改类。 问题是当我使用 waitForSelector 函数时,它不起作用,因为没有新元素添加到 DOM 中。然而,元素 我需要等待一个元素改变类。 问题是当我使用 waitForSelector 函数时,它不起作用,因为没有新元素添加到 DOM 中。然而,<div>元素改变了它的类名。 等待元素直到其类名更改,或等到某个类名出现的正确方法是什么? 我当前的代码: import type { NextApiRequest, NextApiResponse } from "next"; const puppeteer = require("puppeteer"); export default async function handler( req: NextApiRequest, res: NextApiResponse ) { const browser = await puppeteer.launch({ executablePath: "../../../../../../Program Files (x86)/Google/Chrome/Application/chrome.exe", headless: false, }); const page = await browser.newPage(); await page.goto("https://www.craiyon.com/", { timeout: 0, waitUntil: "domcontentloaded", }); await page.waitForTimeout(1000); await page.type(".svelte-1g6bo9g", "sausage"); await page.click("#generateButton"); const test = await page.waitForSelector( ".h-full.w-full.cursor-pointer.rounded-lg.border.border-medium-blue.object-cover.object-center.transition-all.duration-200.hover:scale-[0.97].hover:border-2.hover:border-grey", { timeout: 0, } ); await browser.close(); console.log(test); res.status(200).json({ test: "test" }); } 这是稍后更改的类名: .h-full.w-full.cursor-pointer.rounded-lg.border.border-medium-blue.object-cover.object-center.transition-all.duration-200.hover:scale-[0.97].hover:border-2.hover:border-grey 最后,这是我想要获取的类名:.grid.grid-cols-3.gap-1.sm:gap-2。 我相信你误解了waitForSelector。它不关心元素是新创建的还是已经存在并且有新的类修改。两者都是 DOM 突变,并且将注册为匹配项。 您可以等待您想要存在的选择器,而不是使用等待消失的旧选择器。一旦选择器准备好,waitForSelector就会立即解析,无论它如何进入 DOM 或位于哪个元素上。 如果你想等待某些东西消失或改变,你可以使用waitForFunction,这是waitForSelector的更通用版本。 此外,:表示伪选择器——它在技术上是有效的,但与.sm:gap-2不匹配。您可以将该类排除在外,或者使用建议的属性样式选择器在此评论中,但需要注意的是,这些选择器可能过于挑剔——如果顺序发生变化,它将失败。 暂时忽略这一部分似乎没问题,我们可以从响应中获取 URL,我猜这是我们最关心的: const puppeteer = require("puppeteer"); // ^19.6.3 const url = "<Your URL>"; let browser; (async () => { browser = await puppeteer.launch(); const [page] = await browser.pages(); await page.goto(url, {waitUntil: "domcontentloaded"}); await page.type("#prompt", "sausage"); const imgUrls = new Set(); const responsesArrived = Promise.all( [...Array(9)].map(() => page.waitForResponse( res => { if ( res.request().resourceType() === "image" && res.url().startsWith("https://img.craiyon.com") && res.url().endsWith(".webp") && !imgUrls.has(res.url()) ) { imgUrls.add(res.url()); return true; } }, {timeout: 120_000} ) ) ); await page.click("#generateButton"); const responses = await responsesArrived; console.log([...imgUrls]); const grid = await page.waitForSelector( ".grid.grid-cols-3.gap-1" ); await grid.screenshot({path: "test.png"}); })() .catch(err => console.error(err)) .finally(() => browser?.close()); 建议: 尽量避免waitForTimeout。它已被弃用并导致竞争条件,要么减慢脚本速度,要么使其随机失败。 Puppeteer 的文档建议不要使用它。 切勿使用timeout: 0,尤其是在调试脚本时。没有理由永远阻止。如果选择器失败,并且您的脚本从未报告失败发生的位置,而是挂起,那么您会错过重要的诊断信息。如果您确实必须等待某些事情,否则您的计算机会爆炸,请将等待时间设置为 10 分钟、一天或一周(如果您确实希望某件事需要那么长时间),但不要无限期。如果是关键任务,您可以接住投掷并重试该操作。 避免长选择器。它们通常很脆弱,因为它们对页面上的结构或类假设太多。这个页面有点敌意,提供了一些高质量的元素挂钩,但它仍然值得记住。通常认为最好通过用户可见的属性(例如角色和文本)进行选择。 该网站加载了大量垃圾资源,因此您可以通过阻止您不需要的所有内容来加快速度并节省资源。您可以使用 page.on("request", req => console.log(req.url()) 查看所有 URL,然后系统地阻止与获取结果无关的 URL。 披露:我是链接博客文章的作者。
我正在尝试使用 Puppteer 获取特定网络请求的时间。 有没有办法在 Puppteer 中过滤来自 Chrome DevTools 协议的请求,以便仅在