【问题标题】:Using puppeteer to perform multiple actions at the same time with data obtained from the user使用 puppeteer 使用从用户获取的数据同时执行多个动作
【发布时间】:2018-08-30 05:09:10
【问题描述】:

好吧,我正在尝试构建一个具有客户端界面的应用程序,用户可以在其中放置信息(例如登录 ID 和密码)。

我想要实现的是,每次新用户注册并在客户端界面上设置信息时,该信息将被发送到服务器,木偶脚本将使用它在另一个网页中执行操作。

因此,假设此信息是用户的 Twitter ID 和密码。我希望 puppeteer 使用该信息登录用户的 Twitter 帐户并检索一些特定数据。

我的问题如下:

-用puppeteer可以做到吗?

-如何以 puppeteer 可以获取信息并启动新浏览器任务的方式将信息从客户端发送到服务器端?

感谢您的帮助!

【问题讨论】:

    标签: node.js puppeteer


    【解决方案1】:

    要将信息从客户端发送到服务器,您可以(例如)使用 jQuery ajax (http://api.jquery.com/jquery.ajax/) 或 axios (https://github.com/axios/axios) 使用用户名和密码向服务器发送 post 请求在体内。

    以下是有关如何登录然后转到用户设置页面并从那里删除用户选择的语言的示例。它应该在 99% 的时间内工作,尽管我注意到 Twitter 有时会提供带有不同类选择器的不同加载页面,因此如果你希望它在 100% 的时间内工作,你必须适当地处理它。

    在这种情况下,您将post 请求发送到/puppeteer 端点。 req.body 是您的ajax 请求的数据/正文,格式应为:{ username: 'username', password: 'password' }。如果您将headless参数设置为true,Puppeteer 将打开一个 Chromium 浏览器窗口,您可以在其中看到整个过程。

    const express = require('express')
    const app = express()
    const bodyParser = require('body-parser')
    app.use(bodyParser.json())
    app.use(bodyParser.urlencoded({ extended: false }))
    app.set('trust proxy')
    const puppeteer = require('puppeteer')
    const http = require('http')
    
    app.post('/puppeteer', async (req, res) => {
        const LOGIN_URL = `https://twitter.com/login`
        const ACCOUNT_URL = `https://twitter.com/settings/account`
        const CREDENTIALS = req.body
    
        // Setting up Puppeteer
        const browser = await puppeteer.launch({ headless: false })
        const page = await browser.newPage()
        await page.setViewport({ width: 1920, height: 926 })
    
        // Go to login page
        await page.goto(LOGIN_URL)
    
        // Let's wait until submit button is available, without this you won't be able to login
        await page.waitForSelector('.submit')
    
        // Let's fill in the form and submit it
        await page.$eval('.js-username-field', (el, payload) => el.value = payload, CREDENTIALS.username)
        await page.$eval('.js-password-field', (el, payload) => el.value = payload, CREDENTIALS.password)
        await page.click('button.submit')
    
        // Wait for navigation in case there's some redirect
        await page.waitForNavigation()
    
        // We are logged in, now navigate to the page you want to get data from, i.e. account settings
        await page.goto(ACCOUNT_URL)
    
        // Wait for #user_lang select list
        await page.waitForSelector('#user_lang')
    
        // Find out what's user's selected language (there might be a better way to do this, I rarely need to do DOM manipulations)
        const userLanguage = await page.$eval('#user_lang', languages => [].map.call(languages, lang => { return { lang: lang.textContent, selected: lang.selected } }).find(el => el.selected).lang)
    
        // This scenario assumes we succeed, so I return a successful response, but you might want to return different error codes based on results
        return res.status(200).json(userLanguage)
    })
    
    const server = http.createServer(app)
    server.listen(8000)
    

    【讨论】:

    • 太棒了。非常感谢您的回答!帮助很大:)
    • 表单填写部分的参数'payload'是什么意思?
    • 您不能将 CREDENTIALS 直接传递到您的页面评估部分,因此必须通过将其作为有效负载传递来访问它。名称可以不同。
    • 能否请您进一步解释一下payload主题?我不熟悉它。
    猜你喜欢
    • 1970-01-01
    • 2019-04-12
    • 2020-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-17
    相关资源
    最近更新 更多