【问题标题】:Why will puppeteer not click on the video为什么puppeteer不会点击视频
【发布时间】:2022-01-14 12:38:32
【问题描述】:

我目前正在编写一个简单的程序,该程序从我的 discord 机器人中获取歌曲名称,找到视频并将其传递给函数以转换为 mp3。我的问题是 puppeteer 没有点击视频,而是返回搜索页面链接。

这是我获取链接并通过下载传递的代码:

async function findSongName(stringWithName){

    let stringName = stringWithName.replace(commands.play, '')
    const link = 'https://www.youtube.com';

    const browser = await puppeteer.launch();
    const page = await browser.newPage();
    await page.goto(link)
    
    await page.type('ytd-searchbox#search.style-scope.ytd-masthead', stringName);
    page.keyboard.press('Enter');
    await page.click('yt-interaction#extended');
    console.log(page.url())

    await browser.close()
}

【问题讨论】:

  • 我认为我没有完全理解这里的流程——你搜索一下,然后呢?您想点击顶部视频并播放吗?你如何录制mp3?对于初学者,在单击结果之前,您似乎需要waitForNavigationwaitForSelector。对您想要完成的工作提供更多指导会有所帮助。无论如何,如果是我,我只会使用 youtube-dl 来获取音频或类似的东西,而不需要 Puppeteer。
  • 嘿,我会试着解释得更好一点。我正在尝试单击在搜索栏中键入并拉出该视频链接后弹出的第一个视频。问题是没有弹出错误,而是单击视频并返回视频链接,而是返回搜索查询的链接。我将尝试 youtube-dl,因为我只是想获取链接并将其下载到 mp3

标签: javascript node.js puppeteer


【解决方案1】:

听起来您想获取 YT 搜索的顶部结果的标题和 URL。对于初学者,您无需从 YT 主页开始。只需导航至 https://www.youtube.com/results?search_query=${yourQuery} 即可加快处理速度并降低复杂性。

接下来,如果您查看/results 的页面源,有一个名为ytInitialData 的大型(~1 MB)全局数据结构,其中包含所有相关结果(以及许多其他不相关的内容,诚然)。从理论上讲,您可以使用Axios 获取页面,使用Cheerio 解析出ytInitialData,使用纯数组/对象JS 获取数据并完全跳过Puppeteer。

当然,使用YT search API 是最可靠和正确的方式。

由于您使用的是 Puppeteer,因此可以从 "#items a#video-title" 元素中提取数据,如下所示:

const puppeteer = require("puppeteer");

const searchYT = async (page, searchQuery) => {
  const encodedQuery = encodeURIComponent(searchQuery);
  const url = `https://www.youtube.com/results?search_query=${encodedQuery}`;
  await page.goto(url);
  const sel = "a#video-title";
  await page.waitForSelector(sel);
  return page.$$eval(sel, els =>
    els.map(e => ({
      title: e.textContent.trim(),
      href: e.href,
    }))
  );
};

let browser;
(async () => {
  browser = await puppeteer.launch({headless: true});
  const [page] = await browser.pages();
  await page.setRequestInterception(true);
  page.on("request", req => {
    req.resourceType() === "image" ? req.abort() : req.continue();
  });
  const results = await searchYT(page, "stack overflow");
  console.log(results);
})()
  .catch(err => console.error(err))
  .finally(() => browser?.close())
;

输出(对于搜索词“堆栈溢出”):

[
  {
    title: 'Stack Overflow is full of idiots.',
    href: 'https://www.youtube.com/watch?v=I_ZK0t9-llo'
  },
  {
    title: "How To Use Stack Overflow (no, ForrestKnight, it's not full of idiots)",
    href: 'https://www.youtube.com/watch?v=sMIslcynm0Q'
  },
  {
    title: 'How to use Stack Overflow as a Beginner ?',
    href: 'https://www.youtube.com/watch?v=Vt-Wf7d0CFo'
  },
  {
    title: 'How Microsoft Uses Stack Overflow for Teams',
    href: 'https://www.youtube.com/watch?v=mhh0aK6yJgA'
  },
  // ...
]

既然您只想要第一个结果,那么它就在这里,但如果您想要的不仅仅是初始批次,请如上所述通过 ytInitialData 工作,或者使用 Puppeteer 向下滚动页面。

既然您有一个想要制作成 mp3 的视频 URL,我建议您使用 youtube-dl。您可以安装 Node 包装器以轻松访问其 API,例如 node-youtube-dl,这是我搜索时的第一个结果,我以前从未使用过。

【讨论】:

  • 对于那个搜索结果页面,你想要的一切都在#content#items 对应于“人们也看过”标题,这是 meme 视频所在的位置。选择器的问题在于,YT 可以为您提供带有任意选择器的任意搜索结果页面——这就是像这样抓取主要网站的性质/风险。我更新了帖子以使用a#video-title 而不是#items a#video-title,这似乎解决了当前的问题,但这只是一个概念证明,随着 YT 的发展,几乎肯定需要调整,或者将您发送到 A/B 页面,等
  • 感谢您的回答,我像您一样更新了代码,现在它完全返回了我需要的内容。非常感谢您的帮助,因为我已经坚持了几天了
猜你喜欢
  • 2020-06-12
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
  • 2018-10-05
  • 2021-04-30
  • 1970-01-01
  • 2013-04-14
  • 2019-11-14
相关资源
最近更新 更多