使用pyppeteer替代selenium模拟登录谷歌Youtube

前言

之前大家使用selenium的无头浏览器的时候用的是phantomjs,自从phantomjs慢慢不更新了之后,selenium也开始找下家,这时候谷歌的chrome率先搞出来无头浏览器并开放了各种api,随后firefox也开始做。
现在selenium的测试也都支持这两个浏览器的无头模式了,只需要在引入的时候配置一下就可以了。
但是今天的主角并不是selenium,之所以要采用谷歌chrome官方无头框架puppeteer的python版本pyppeteer,是因为有些网页是可以检测到是否是使用了selenium。并且selenium所谓的保护机制不允许跨域cookies保存以及登录的时候必须先打开网页然后后加载cookies再刷新的方式都让我很难受,虽然也有解决方案,但是既然有更好用的新鲜事物,还是要尝试一下了。

环境搭建与准备

测试环境:Win7 64位、 python3.6

而之所以是3.6是因为最新版pyppeteer只对于python3.6和3.7有更好的支持,python2.x版本由于没有asyncio这个库,根本不可用。

pyppeteer安装

先安装python3.6,再用命令python3 -m pip install pyppeteer进行安装即可。
如果你跟我一样用pycharm这个编辑器,那么直接在编辑器项目设置里点击加号搜索pyppeteer点击Install Package安装即可。
《使用pyppeteer替代selenium模拟登录谷歌Youtube》

首次启动与chromium的下载

使用示例代码进行运行方便进行chromium的自动下载:

import asyncio
from pyppeteer import launch

async def main():
    browser = await launch({'headless': False})
    page = await browser.newPage()
    await page.goto('http://example.com')
    await page.screenshot({'path': 'example.png'})
    await browser.close()

asyncio.get_event_loop().run_until_complete(main())

首次运行会自动下载chrome的开源版chromium,国内用户会遇到被墙问题,这时候只要把$$R之类的软件开启全局或者pac模式即可,而无需安装node.js、npm之类的东西。如果还是下载不了,就在手动下载https://storage.googleapis.com/chromium-browser-snapshots/Win_x64/575458/chrome-win32.zip ,然后解压放到C:\Users\Administrator\AppData\Local\pyppeteer\pyppeteer\local-chromium\575458\chrome-win32里即可。
设置’headless’: False是方便查看是否chromium已经下载并安装成功了,也方便前期进行调试,等都弄好了,就可以去掉了,程序再运行的时候浏览器也不会弹出来了,而只是在进程里运行了。
如果还是无法解决,也可以使用新版的chrome浏览器,只要在launch里配置一下chrome的路径即可。'executablePath': 'C:\Program Files (x86)\Google\Chrome\Application\chrome.exe',

谷歌Youtube的登录

定位元素

  1. 下图为https://gmail.com 打开后的登录页面,你也可以使用Youtube的网址进行登录,但是最终都是到达下图这个页面,我个人是先打开gmail进行登录,登录成功后,想打开哪个谷歌系列全家桶页面直接打开即可,默认会带上登录状态的。
    《使用pyppeteer替代selenium模拟登录谷歌Youtube》

  2. 使用chrome右键审查元素(也有的叫检查),对Email框进行定位,并获取selector为:#identifierId
    《使用pyppeteer替代selenium模拟登录谷歌Youtube》
    继续获取Next按钮为:#identifierNext > content
    点击Next,获取密码框为:#password > div.aCsJod.oJeWuf > div > div.Xb9hP > input,这是在浏览器直接复制到的css selector,可以看到里面有div.aCsJod.oJeWuf和div.Xb9hP这种不规则的东西,这个对于不同浏览器可能不同,也可能是随机变化的数值,这种这次复制是这样,下次可能就不是了,这时候就需要对selector进行优化,改为#password input,至于为什么改成这样,并想深入学习请参考:CSS 选择器参考手册
    《使用pyppeteer替代selenium模拟登录谷歌Youtube》
    获取Next按钮为:#passwordNext > content > span
    点击Next到达安全页面:
    《使用pyppeteer替代selenium模拟登录谷歌Youtube》
    到这里就已经算是登录成功了,这个页面只需要获取到Done按钮的selector就够了。直接复制的为#yDmH0d > c-wiz.yip5uc.SSPGKf > c-wiz > div > div.p9lFnc > div > div > div > div.ZRg0lb.Kn8Efe > div:nth-child(3) > div > div.yKBrKe > div > content > span,对于这种就已经不能直接用复制的selector了,因为我们需要获取的是唯一元素,而这个太长并且里面动态的参数太多。这就需要对selector进行改编了。改为:div > content > span
    对于这种需要改动太大的,并且自己拿不准到底改的对不对,可以通过chrome浏览器调试工具Console填写$("你的css selector代码")进行测试,也可以安装chrome的SelectorGadget插件来进行验证。

  3. 至此我们获得了登录的整个流程需要定位的元素,对于需要输入的使用page.type()进行输入,使用page.click()对需要点击的按钮进行点击。

跳转到Youtube

登录成功后,只需要直接使用await page.goto('https://www.youtube.com')进行跳转即可,自动带上登录状态。

Gmail模拟登录完整代码

下面为完整代码,python只是自学兴趣,写的不好请多多见谅。

import asyncio
import time
from pyppeteer import launch

async def gmailLogin(username, password, url):
    #'headless': False如果想要浏览器隐藏更改False为True
    # 127.0.0.1:1080为代理ip和端口,这个根据自己的本地代理进行更改,如果是vps里或者全局模式可以删除掉'--proxy-server=127.0.0.1:1080'
    browser = await launch({'headless': False, 'args': ['--no-sandbox', '--proxy-server=127.0.0.1:1080']})
    page = await browser.newPage()
    await page.setUserAgent(
        'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36')

    await page.goto(url)

    # 输入Gmail
    await page.type('#identifierId', username)
    # 点击下一步
    await page.click('#identifierNext > content')
    page.mouse  # 模拟真实点击
    time.sleep(10)
    # 输入password
    await page.type('#password input', password)
    # 点击下一步
    await page.click('#passwordNext > content > span')
    page.mouse  # 模拟真实点击
    time.sleep(10)
    # 点击安全检测页面的DONE
    # await page.click('div > content > span')#如果本机之前登录过,并且page.setUserAgent设置为之前登录成功的浏览器user-agent了,
    # 就不会出现安全检测页面,这里如果有需要的自己根据需求进行更改,但是还是推荐先用常用浏览器登录成功后再用python程序进行登录。

    # 登录成功截图
    await page.screenshot({'path': './gmail-login.png', 'quality': 100, 'fullPage': True})
    #打开谷歌全家桶跳转,以Youtube为例
    await page.goto('https://www.youtube.com')
    time.sleep(10)

if __name__ == '__main__':
    username = '你的gmail包含@gmail.com'
    password = r'你的gmail密码'
    url = 'https://gmail.com'
    loop = asyncio.get_event_loop()
    loop.run_until_complete(gmailLogin(username, password, url))
# 代码由三分醉编写,网址www.sanfenzui.com,参考如下文章:
# https://blog.csdn.net/Chen_chong__/article/details/82950968

里面的time.sleep(10)只是测试的时候延时10秒,看是否输入成功了,具体使用的时候可以去掉。
page.mouse # 模拟真实点击,看别人是这么写的,具体有没有效果不知道,为了防止被封号还是加上吧,又弄得跟玄学一样了,有这方面的专业的朋友欢迎留言解惑,万分感谢!

本文由三分醉博客原创,转载请注明:https://www.sanfenzui.com/use-pyppeteer-instead-of-selenium-simulate-log-in-google-youtube.html

文章同步更新在知乎:三分醉 – 知乎

点赞
  1. Karolina说道:

    嗨,我喜欢看你的文章。我有兴趣建立伙伴关系。你能通过电子邮件回复我吗?谢谢

发表评论

电子邮件地址不会被公开。 必填项已用*标注