module BrowserHuman
BrowserHuman — natural pointer paths for headless browser challenge interaction. Public: bezier_path, natural_move, natural_click, idle_wander Tests: test/lib/browser_human_test.rb
Constants
- DEFAULT_STEPS
- MAX_SLEEP_SEC
- MIN_SLEEP_SEC
Public Instance Methods
Source
# File lib/browser_human.rb, line 14 def bezier_path(x0, y0, x1, y1, steps: DEFAULT_STEPS, rand_fn: nil) random = rand_fn || method(:rand) steps = [steps.to_i, 2].max cp1x = x0 + (x1 - x0) * random_fraction(random, 0.2, 0.45) cp1y = y0 + (y1 - y0) * random_fraction(random, -0.35, 0.35) cp2x = x0 + (x1 - x0) * random_fraction(random, 0.55, 0.85) cp2y = y0 + (y1 - y0) * random_fraction(random, 0.65, 1.35) (1..steps).map do |step| t = step / steps.to_f u = 1.0 - t x = (u**3 * x0) + (3 * u**2 * t * cp1x) + (3 * u * t**2 * cp2x) + (t**3 * x1) y = (u**3 * y0) + (3 * u**2 * t * cp1y) + (3 * u * t**2 * cp2y) + (t**3 * y1) if step < steps jitter = random_fraction(random, -1.5, 1.5) x += jitter y += (jitter * 0.6) end [x, y] end end
Source
# File lib/browser_human.rb, line 55 def idle_wander(mouse, width:, height:, sleep_fn: nil, rand_fn: nil) random = rand_fn || method(:rand) sleeper = sleep_fn || method(:sleep) moves = random_between(random, 1, 3) moves.times do target_x = random_between(random, 40, width - 41) target_y = random_between(random, 40, height - 41) natural_move(mouse, x: target_x, y: target_y, sleep_fn: sleeper, rand_fn: random) sleeper.call(random_between(random, 50, 150) / 1000.0) end mouse end
Source
# File lib/browser_human.rb, line 85 def mouse_position(mouse) if mouse.respond_to?(:current_position) mouse.current_position else [mouse.instance_variable_get(:@x) || 0, mouse.instance_variable_get(:@y) || 0] end end
Source
# File lib/browser_human.rb, line 47 def natural_click(mouse, x:, y:, sleep_fn: nil, rand_fn: nil) random = rand_fn || method(:rand) sleeper = sleep_fn || method(:sleep) natural_move(mouse, x: x, y: y, sleep_fn: sleeper, rand_fn: random) sleeper.call(random_fraction(random, 0.04, 0.12)) mouse.click(x: x, y: y) end
Source
# File lib/browser_human.rb, line 36 def natural_move(mouse, x:, y:, sleep_fn: nil, rand_fn: nil) random = rand_fn || method(:rand) sleeper = sleep_fn || method(:sleep) from_x, from_y = mouse_position(mouse) bezier_path(from_x, from_y, x, y, rand_fn: random).each do |px, py| mouse.move(x: px, y: py, steps: 1) sleeper.call(random_fraction(random, MIN_SLEEP_SEC, MAX_SLEEP_SEC)) end mouse end
Source
# File lib/browser_human.rb, line 68 def random_between(random, min, max) if random.equal?(method(:rand)) random.call(min..max) else span = max - min + 1 min + (random.call(span).to_i % span) end end
Source
# File lib/browser_human.rb, line 77 def random_fraction(random, min, max) if random.equal?(method(:rand)) random.call(min..max) else min + ((random.call(1000).to_f % 1000) / 1000.0) * (max - min) end end