Mouse
O Pydoll controla o mouse de duas formas: através de um elemento que você encontrou, que é o que você quer na maior parte do tempo, ou em coordenadas brutas da página quando você precisa de posições precisas. Ambas suportam humanize=True, que move o cursor por um caminho curvo, com tempo humano, em vez de teleportar para o alvo.
Clicar em um elemento
O caso comum é clicar em um elemento que você já localizou com find() ou query(). Chame click() nele; você não calcula coordenadas, e o elemento é rolado para a área visível primeiro.
import asyncio
from pydoll.browser.chromium import Chrome
async def main():
async with Chrome() as browser:
tab = await browser.start()
await tab.go_to('https://the-internet.herokuapp.com/add_remove_elements/')
add_button = await tab.find(text='Add Element')
await add_button.click()
# o clique adicionou um botão Delete
delete = await tab.find(class_name='added-manually')
print('Added:', await delete.text)
asyncio.run(main())
O click() recebe algumas opções:
# clica em um ponto deslocado do centro do elemento (pixels)
await element.click(x_offset=10, y_offset=5)
# mantém o botão pressionado por mais tempo antes de soltar (segundos)
await element.click(hold_time=0.3)
# humanizado: caminho curvo do cursor até o elemento, depois clique
await element.click(humanize=True)
Clique em elemento vs coordenadas brutas
Prefira element.click(). Ele encontra a posição do elemento para você e sobrevive a mudanças de layout. Recorra à API de coordenadas abaixo apenas quando não há elemento a mirar, como clicar dentro de um <canvas> ou arrastar um controle por pixel.
A API de mouse por coordenadas
tab.mouse clica, move e arrasta em coordenadas explícitas em pixels CSS, medidas a partir do canto superior esquerdo da página. Você geralmente obtém essas coordenadas a partir dos limites de um elemento (veja Arrastar um slider).
import asyncio
from pydoll.browser.chromium import Chrome
from pydoll.protocol.input.types import MouseButton
async def main():
async with Chrome() as browser:
tab = await browser.start()
await tab.go_to('https://the-internet.herokuapp.com/')
await tab.mouse.move(500, 300) # move o cursor
await tab.mouse.click(500, 300) # clique esquerdo
await tab.mouse.click(500, 300, button=MouseButton.RIGHT) # clique direito
await tab.mouse.double_click(500, 300) # clique duplo
await tab.mouse.drag(100, 200, 500, 400) # pressiona, move, solta
asyncio.run(main())
O MouseButton (de pydoll.protocol.input.types) tem LEFT, MIDDLE e RIGHT. O click() também recebe click_count (passe 2 para um clique duplo) e todo método recebe o humanize (apenas por palavra-chave).
Para pressionar e soltar separadamente, down() e up() operam na posição atual do cursor:
await tab.mouse.move(300, 400)
await tab.mouse.down(button=MouseButton.LEFT)
await tab.mouse.move(600, 400) # arraste manualmente
await tab.mouse.up(button=MouseButton.LEFT)
O tab.mouse rastreia a posição do cursor entre chamadas, então down()/up() agem onde quer que o último move() ou click() tenha deixado.
Mover como um humano
Por padrão, um movimento ou clique salta direto para o alvo, o que é um indício comportamental. Passe humanize=True e o Pydoll move o cursor por um caminho curvo com tempo humano (uma duração baseada na Lei de Fitts, um perfil de velocidade em forma de sino, um pequeno tremor, e ocasional ultrapassagem com correção):
await tab.mouse.move(500, 300, humanize=True)
await tab.mouse.click(500, 300, humanize=True)
await tab.mouse.drag(100, 200, 500, 400, humanize=True)
Dois movimentos humanizados: caminhos curvos com easing e um leve overshoot, não saltos retos.
Cliques humanizados em elementos funcionam da mesma forma. Como a posição é rastreada, clicar no elemento A e depois no elemento B traça uma curva natural de um para o outro:
# instantâneo: o cursor salta direto para cada alvo
await (await tab.find(id='first')).click()
await (await tab.find(id='second')).click()
# humanizado: o cursor curva naturalmente de um alvo para o próximo
await (await tab.find(id='first')).click(humanize=True)
await (await tab.find(id='second')).click(humanize=True)
Veja Interações humanizadas para o modelo completo de tempo e quando a humanização importa.
Ajustar o tempo
A física humanizada é configurável através de MouseTimingConfig. Atribua uma nova config a tab.mouse.timing:
from pydoll.interactions.mouse import MouseTimingConfig
tab.mouse.timing = MouseTimingConfig(
fitts_a=0.070, # tempo base de movimento (segundos)
fitts_b=0.150, # tempo adicionado por bit de dificuldade
curvature_min=0.10, # menor curvatura do caminho (fração da distância)
curvature_max=0.30, # maior curvatura do caminho
tremor_amplitude=1.0, # sigma do tremor da mão em pixels
overshoot_probability=0.70, # chance de ultrapassagem em movimentos rápidos e longos
max_duration=2.5, # limite para um único movimento (segundos)
)
Todo campo tem um valor padrão, então sobrescreva apenas o que precisar. Veja a dataclass MouseTimingConfig em pydoll/interactions/mouse.py para a lista completa.
Observar o cursor durante o ajuste
Defina tab.mouse.debug = True e o Pydoll desenha o caminho do cursor sobre uma sobreposição transparente: pontos azuis traçam o movimento, pontos vermelhos marcam os cliques. Use para verificar se os caminhos humanizados parecem naturais, depois desligue.
Exemplos práticos
Arrastar um slider
Leia a posição do controle a partir dos seus limites, depois arraste de lá:
slider = await tab.query('.slider-handle')
bounds = await slider.get_bounds_using_js() # {'x', 'y', 'width', 'height'}, pixels do viewport
start_x = bounds['x'] + bounds['width'] / 2
start_y = bounds['y'] + bounds['height'] / 2
await tab.mouse.drag(start_x, start_y, start_x + 200, start_y, humanize=True)
Arrastando o handle por um caminho humanizado.
Passar o cursor sobre um menu
Mova o cursor até um elemento para acionar seu estado CSS :hover, sem clicar:
trigger = await tab.query('.dropdown-trigger')
bounds = await trigger.get_bounds_using_js()
await tab.mouse.move(
bounds['x'] + bounds['width'] / 2,
bounds['y'] + bounds['height'] / 2,
humanize=True,
)
O cursor entra no gatilho, o dropdown expande e para em um item.
Próximos passos
- Teclado: digite texto e pressione teclas, com o mesmo tempo humanizado.
- Interações humanizadas: o modelo de tempo por trás de
humanize=Truee quando usá-lo. - Encontrar elementos: localize os elementos que você clica e arrasta.