【问题标题】:Is there a way to click in headless chrome?有没有办法点击无头镀铬?
【发布时间】:2019-12-12 10:26:59
【问题描述】:

我正在尝试点击 Linkedin 个人资料中的“我的网络”按钮。我可以使用 'goto' 方法直接转到该网址,但我希望能够点击它。

我曾尝试使用“复制选择器”,但它似乎不起作用。

const BUTTON_SELECTOR = '#mynetwork-nav-item';
    await page.click(BUTTON_SELECTOR);

我可以登录,但之后就无法登录了。

完整代码-

const puppeteer = require('puppeteer');
(async () => {
  /* Initiate the Puppeteer browser */
  const browser = await puppeteer.launch({ headless: false, defaultViewport: { width: 1366, height: 768 }});
  const page = await browser.newPage();

  await page.goto(`https://www.linkedin.com`, { waitUntil: 'networkidle0' });

  let element, formElement, tabs;
  element = await page.$x(`//a[contains(text(),'Sign in')]`);
    await element[0].click();
    await page.waitForNavigation();

    element = await page.$x(`//*[@id="username"]`);
    await element[0].type(`some_id@example.com`);

    element = await page.$x(`(.//*[normalize-space(text()) and normalize-space(.)='Welcome Back'])[1]/following::div[3]`);
    await element[0].click();

    element = await page.$x(`//*[@id="password"]`);
    await element[0].click();

    element = await page.$x(`//*[@id="password"]`);
    await element[0].type(`some_password`);

    await page.keyboard.press(`Enter`)

    const MY_NETWORK_BUTTON = '#mynetwork-tab-icon';
    await page.waitForSelector(MY_NETWORK_BUTTON, {visible: true});
    const [response] = await Promise.all([
    page.waitForNavigation(), // The promise resolves after navigation has finished
    page.click(MY_NETWORK_BUTTON), // Clicking the link will indirectly cause a navigation
    ]);

    console.log('CURRENT URL IS: ', response.url());
})();

【问题讨论】:

    标签: node.js puppeteer google-chrome-headless


    【解决方案1】:

    首先尝试等待选择器,然后您应该更改选择器,然后单击它。

    更新:

    const MY_NETWORK_BUTTON = '#mynetwork-tab-icon';
    await page.waitForSelector(MY_NETWORK_BUTTON, {visible: true});
    const [response] = await Promise.all([
      page.waitForNavigation(), // The promise resolves after navigation has finished
      page.click(MY_NETWORK_BUTTON), // Clicking the link will indirectly cause a navigation
    ]);
    
    console.log('CURRENT URL IS: ', response.url());
    

    输出:

    当前网址为:https://www.linkedin.com/mynetwork/

    【讨论】:

    • 你在页面上测试过这个吗?因为它似乎对我不起作用。
    • 是的,它可以工作,只是用你编辑的代码检查过它仍然可以工作。
    • 您可以检查 url 是否已更改并且您在我的网络页面上。我已经用console.log 更新了答案。请检查一下,然后告诉我它是什么意思
    • 错误消息:(节点:30434)UnhandledPromiseRejectionWarning:TypeError:无法读取/home/kaustubh/imdb.js:35:43 at process._tickCallback(内部/流程/ next_tick.js:68:7) (node:30434) UnhandledPromiseRejectionWarning: 未处理的承诺拒绝。
    【解决方案2】:

    只需等待导航完成就足以正确更改选项卡

    await Promise.all([
        page.waitForNavigation(),
        page.click(MY_NETWORK_BUTTON)
    ]);
    

    但是问题可能出在其他地方,例如,当我最初创建帐户时,网页提示我在登录后立即添加我的电话号码,因此您可能无法单击网络选项卡,因为此选择器在某些情况下不存在其他原因。

    通常不建议使用表单登录,因为许多网页都有针对抓取/非人类用户的对策。特别是Linkedin可以要求你在登录后完成验证码以证明你不是机器人。

    如果您真的想以这种方式登录,您可以通过将这些选择器更改为简单的方式来改进您的代码

    await page.goto("https:\/\/www.linkedin.com", { waitUntil: 'networkidle0' });
    
    await page.type("input[name='session_key']",email);
    await page.type("input[name='session_password']",password);
    await page.keyboard.press(`Enter`);
    

    否则我会建议使用 cookie 登录,这样会更加简化代码。

    您可以通过调用以 puppeteer 接受的格式获取 cookie 列表

    await page.cookies();
    

    然后将它们设置为

    await page.setCookie(cookie)
    

    我不太确定linkedin 用于在cookie 中存储用户信息的格式,但似乎只加载名为li_at 的cookie 就足够了,例如

    await page.setCookie({
        "name": "li_at",
        "value": INSERT VALUE HERE,
        "domain": ".www.linkedin.com",
        "path": "/",
        "size": 157,
        "httpOnly": true,
        "secure": true,
        "session": false
    })
    

    【讨论】:

    • 我已经看到进程在“headless: false”模式下的响应,该页面中没有弹出窗口。我收到以下错误 - (node:31195) UnhandledPromiseRejectionWarning: ReferenceError: response is not defined at /home/kaustubh/imdb.js:35:34 at process._tickCallback (internal/process/next_tick.js:68:7) (节点:31195)UnhandledPromiseRejectionWarning:未处理的承诺拒绝。此错误源于在没有 catch 块的情况下抛出异步函数内部,或拒绝未使用 .catch() 处理的承诺。 (拒绝 ID:1)
    • 此错误与所描述的问题无关,您的代码中似乎存在某些问题(`/home/kaustubh/imdb.js:35:34`)您正在引用不存在的响应对象。
    • imdb.js 是此文件的名称。很抱歉造成混乱。
    • 我确实意识到这很可能是该文件的名称,但似乎并非所有代码都是由您提供的(特别是导致问题的部分)
    • 很抱歉给您带来了困惑。我已经更新了代码。请看一看。
    猜你喜欢
    • 2017-12-23
    • 2018-08-24
    • 1970-01-01
    • 1970-01-01
    • 2018-05-03
    • 2018-04-23
    • 2018-01-02
    • 2021-12-03
    • 1970-01-01
    相关资源
    最近更新 更多