最近一直在玩弄异步爬虫, 本文就是基于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())
如果本文对你有启发,或者对本文有疑问或者功能/方法建议,可以在下方做出评论,或者直接联系我,谢谢您的观看和支持!