Pyppeteer使用

最近一直在玩弄异步爬虫, 本文就是基于Pyppeteer所写的一些测试

实际上就是对京东做登录测试, 虽然京东的商品不用登录就能爬取, 这点和淘宝不一样, 少许方便一点

为什么我会考虑用Pyppeteer呢, 实际上Pyppeteer和Selenium算是一家的, Pyppeteer是只能用来操控Chromium浏览器的, Chromium可以当做是Chrome的先行版, 在我这段时间的把玩来说, 运行的速度比Chrome真的快的多了, 不知道什么原因我Selenium操控Chrome时启动浏览器后要发呆很长时间, 而且一些页面操作也相对慢一点

Pyppeteer在针对淘宝和京东的按键检测有很好的帮助, 因为在Selenium时一些登录输入还有滑动滑块, 是无法通过校验的, 原因很简单, Selenium是用dom或者js等方式来完成对浏览器的操控的, 而Pyppeteer则是真实的鼠标或者按键的输入, 这点在输入大小写账号/密码时, 网页上输入框会弹出大小写切换的提示, 凭着这点就绕过了人机测试, 还是很棒的

至于Pyppeteer安装完以后, 第一次运行时他会自动下载Chromium, 但是无奈网络原因我是直接下载的Chromium然后倒入路径的...

但是话说回来, 淘宝在有界面模式下我是能登录了, 没有出现滑块, 当在无界面通过截图发现, 这时候却出现了滑块, 这点有点不解

重点回到京东的滑块, 我在借助打码平台的帮助下进行滑动, 可惜, 充了5块钱也就仅仅成功了一次, 这个成功并不是因为操作的不准确, 在我观察里, 至少90%以上是滑动的很准确的, 那么又为什么失败了呢? 原因是京东的滑块貌似是有高等级的人机检测, 毕竟通过工具再怎么随机滑动, 目前很难办到很像真人, 也不是说没有把, 只能说我功力还不够, 也就是说, 他觉得你不是人为操作的, 就被否决需要重新滑动了

部分历史滑动的准确度:

先分步骤来看看操作随机滑动的代码:

while start_x < move_x:
    start_x += int(random.random() * 20)
    if start_x > move_x:
        start_x = move_x
        await page.mouse.move(start_x, y + random.random(), {'steps': input_time_random()})
        await page.mouse.up()
    else:
        await page.mouse.move(start_x, y + random.random(), {'steps': input_time_random()})

start_x是滑块的起点坐标, move_x是结束的坐标, 通过逐渐随机滑动的方式来达成

但是这样操作出现了一个问题, 当await page.mouse.up()时并没有成功释放鼠标, 这是为什么呢? 我一直在调试, 始终解决不到这个问题, 后来我就想想, 是不是因为滑动了多次就要释放多次? 然后我就尝试着修改代码:

step = []
while start_x < move_x:
    start_x += int(random.random() * 20)
    if start_x > move_x:
        start_x = move_x
    step.append(start_x)
for i in step:
    await page.mouse.move(i, y + random.random() * 20, {'steps': input_time_random()})
for _ in step:
    await page.mouse.up()
await asyncio.sleep(10)

通过这样的方式倒是成功释放了鼠标, 至于为何吗? 还要研究一下...有点耐人寻味(手动滑稽)

如今要提高成功率就得好好的研究模仿人滑动滑块的方式了, 这又是一个大麻烦呢...


完整代码:

import asyncio, random
from pyppeteer import launch
from datisdk import uploadFile, queryJson # 打码平台


width, height = 1440, 900

def input_time_random():
    return random.randint(100, 151)


async def login():
    executablePath = r'E:/chromium/chrome.exe'
    browser = await launch(
        executablePath=executablePath,
        headless=False,
        args=['--disable-infobars',f'--window-size={width},{height}']
    )
    page = await browser.newPage()
    await page.setViewport({'width': width, 'height': height})
    await page.goto('https://www.jd.com/')
    await page.waitFor('#ttbar-login')
    await page.click('#ttbar-login')
    await page.waitFor('.login-tab.login-tab-r > a')
    await page.click('.login-tab.login-tab-r > a')
    await page.waitFor(1 * 1000)
    await page.type('#loginname', '账号', {'delay': input_time_random() - 50})
    await page.waitFor(1 * 1000)
    await page.type('#nloginpwd', '密码', {'delay': input_time_random() - 50})
    await page.waitFor(1 * 1000)
    await page.click('#loginsubmit')
    await page.waitFor(1 * 1000)
    while True:
        slider = await page.querySelector('.JDJRV-bigimg > img')
        if slider:
            jd_code = await page.waitForSelector('.JDJRV-bigimg > img')
            await jd_code.screenshot({'path': 'jd_code.png'})
            # 上传滑块图片到打码平台
            result = uploadFile('./jd_code.png', '平台token', '500020', 'breezed', '')
            while True:
                # 获取滑块坐标
                msg = queryJson('平台token', result['msg'])
                if msg['status'] != 0:
                    pass
                else:
                    index_list = msg['msg'].split('|')
                    first = int(index_list[0].split(',')[0])
                    end = int(index_list[1].split(',')[0])
                    pic_x = end - first
                    break
            # 获取滑块初始按钮坐标
            btn_position = await page.evaluate('''
                   () =>{
                    return {
                     x: document.querySelector('.JDJRV-smallimg').getBoundingClientRect().x,
                     y: document.querySelector('.JDJRV-smallimg').getBoundingClientRect().y,
                     }}
                    ''')
            x, y = btn_position['x'], btn_position['y']
            move_x = x + pic_x
            start_x = x
            # 移动到滑块
            await page.mouse.move(x, y)
            await page.mouse.down()
            step = []
            while start_x < move_x:
                start_x += int(random.random() * 20)
                if start_x > move_x:
                    start_x = move_x
                step.append(start_x)
            for i in step:
                await page.mouse.move(i, y + random.random() * 20, {'steps': input_time_random()})
            for _ in step:
                await page.mouse.up()
            await asyncio.sleep(10)
        else:
            break

if __name__ == '__main__':
    asyncio.get_event_loop().run_until_complete(login())

如果本文对你有启发,或者对本文有疑问或者功能/方法建议,可以在下方做出评论,或者直接联系我,谢谢您的观看和支持!

添加新评论

本站现已启用评论投票,被点踩过多的评论将自动折叠。与本文无关评论请发留言板。请不要水评论,谢谢。

已有 0条评论