Skip to main content

Selenium-style synchronous WebDriver API powered by Python nodriver.

Project description

selenodriver

Selenium-style synchronous WebDriver API powered by Python nodriver.

selenodriver는 기존 Selenium 코드 스타일을 최대한 유지하면서, 내부 동작은 nodriver와 CDP 기반으로 처리하는 호환 레이어입니다.

목차

핵심 강점

  • Selenium과 비슷한 동기 API: await 없이 driver.get(), find_element(), element.click() 형태로 사용합니다.
  • CDP 기반 마우스 클릭: 기본 element.click()은 JS el.click()이 아니라 화면 좌표를 계산해서 Input.dispatchMouseEvent를 보냅니다.
  • 입력 방식 분리: 마우스 클릭, 터치 클릭, JS 클릭을 명확히 나눠서 사용할 수 있습니다.
  • 좌표 기반 제어: element 중앙 클릭뿐 아니라 offset 클릭, 특정 좌표 클릭, element 내부 랜덤 위치 클릭을 지원합니다.
  • 모바일 흐름 지원: 터치 클릭, 터치 스크롤, 더블 탭, 롱 프레스, 터치 드래그, 모바일 에뮬레이션 확장을 제공합니다.
  • Selenium 호환 import: selenodriver.webdriver.* 경로를 지원해 기존 Selenium 코드와 비슷한 구조로 옮기기 쉽습니다.
  • 확장 모듈 구조: 외부/private extension을 붙여 브라우저 시작, 이동, 새 탭, context 변경 시점에 자동 로직을 적용할 수 있습니다.

버전과 의존성

Current package version:

selenodriver 0.1.0

Runtime requirements:

Python >= 3.10
nodriver >= 0.39

nodriver is declared as a package dependency in pyproject.toml, so package installers will install it automatically when installing selenodriver.

dependencies = [
  "nodriver>=0.39",
]

빠른 시작

from selenodriver import ActionChains, By, Chrome, Keys, Options
from selenodriver.support import expected_conditions as EC
from selenodriver.support.ui import WebDriverWait

options = Options()
options.add_argument("--no-first-run")

driver = Chrome(headless=True, options=options)
driver.get("https://example.com")

heading = WebDriverWait(driver, 10).until(
    EC.presence_of_element_located((By.TAG_NAME, "h1"))
)
print(heading.text)

ActionChains(driver).move_to_element(heading).click().send_keys(Keys.ENTER).perform()

driver.quit()

클릭과 입력 방식

selenodriver는 클릭 방식을 의도적으로 분리합니다.

방식 사용 예 내부 동작 용도
기본/마우스 클릭 element.click() CDP Input.dispatchMouseEvent 일반 데스크톱 클릭
명시적 마우스 클릭 element.mouse_click() CDP mousePressed / mouseReleased 기본 클릭과 동일
터치 클릭 element.touch_click() CDP Input.dispatchTouchEvent 모바일 탭에 가까운 입력
JS 클릭 element.js_click() JS el.click() DOM 메서드를 직접 호출해야 할 때

기본 클릭은 element의 화면상 중앙 좌표를 기준으로 마우스 이벤트를 보냅니다. JS 클릭이 필요한 경우에는 js_click()을 별도로 호출합니다.

좌표 클릭 / 랜덤 위치 클릭

Selenium의 ActionChains 스타일로 element 중앙이 아닌 지점을 클릭할 수 있습니다.

from selenodriver import ActionChains

ActionChains(driver) \
    .move_to_element_with_offset(element, xoffset, yoffset) \
    .click() \
    .perform()

xoffset, yoffset은 Selenium 호환 기준으로 element의 중앙점 기준입니다.

element 내부의 랜덤 위치를 클릭하려면 좌상단 기준 랜덤 좌표를 만든 뒤 중앙점 기준 offset으로 변환합니다.

import random
from selenodriver import ActionChains

size = element.size
rx = random.randint(5, int(size["width"]) - 5)
ry = random.randint(5, int(size["height"]) - 5)

xoffset = rx - size["width"] / 2
yoffset = ry - size["height"] / 2

ActionChains(driver) \
    .move_to_element_with_offset(element, xoffset, yoffset) \
    .click() \
    .perform()

같은 위치를 터치 입력으로 누를 수도 있습니다.

ActionChains(driver) \
    .touch_move_to_element_with_offset(element, xoffset, yoffset) \
    .touch_click() \
    .perform()

모바일 관련 기능

모바일 테스트를 위해 다음 기능을 제공합니다.

  • element.touch_click()
  • element.click(input_type="touch")
  • ActionChains(driver).touch_click()
  • ActionChains(driver).double_tap(element)
  • ActionChains(driver).long_press(element)
  • ActionChains(driver).touch_drag_and_drop(source, target)
  • driver.touch_scroll_by(x, y)
  • driver.touch_scroll_to(x, y)
  • element.touch_scroll_into_view()
  • MobileEmulationExtension("android")
  • MobileEmulationExtension("ios")

모바일 에뮬레이션 확장은 UA, viewport, device scale factor, touch emulation, locale, timezone 등을 CDP Emulation.* 명령으로 적용합니다. 브라우저 attach, 페이지 이동, context 변경, 새 탭 감지 시점에 다시 적용됩니다.

from selenodriver import Chrome, MobileEmulationExtension

driver = Chrome(
    extensions=[
        MobileEmulationExtension("android")
    ]
)

직접 프로필 dict도 사용할 수 있습니다.

profile = {
    "device_name": "iPhone 16 Pro",
    "os_type": "ios",
    "width": 402,
    "height": 874,
    "devicePixelRatio": 3.0,
    "UA": "Mozilla/5.0 (iPhone; CPU iPhone OS 18_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/18.0 Mobile/15E148 Safari/604.1",
    "platform": "iPhone",
    "language": "ko-KR",
    "languages": ["ko-KR", "ko"],
}

driver = Chrome(extensions=[MobileEmulationExtension(profile)])

현재 구현 범위

This is an early compatibility layer, not a full Selenium replacement yet.

Implemented:

  • Chrome
  • By
  • WebElement
  • NoSuchElementException
  • WebDriverWait
  • ActionChains
  • Keys
  • Select
  • Options / ChromeOptions
  • MobileEmulationExtension
  • extension hooks for external/private modules
  • Selenium-like import paths under selenodriver.webdriver.*
  • common expected conditions
  • locators: CSS selector, XPath, id, name, tag name, class name
  • element actions/properties: click, mouse_click, touch_click, js_click, submit, scroll_into_view, shadow_root, send_keys, clear, text, tag_name, get_attribute, get_dom_attribute, get_property, value_of_css_property, is_selected, size, location, rect
  • browser helpers: get, back, forward, refresh, extension hooks, init scripts, auto_wait, implicitly_wait, set_script_timeout, timeouts, session_id, capabilities, window size/position, legacy find aliases, find_element, find_element_location, find_element_absolute_location, find_elements, execute_script, send_cdp, scroll_to, scroll_by, touch_scroll_by, touch_scroll_to, page_source, title, current_url, current_window_handle, window_handles, switch_to.window, switch_to.frame, switch_to.active_element, cookies, save_screenshot, close, quit
  • action chains: click, touch_click, double_click, double_tap, context_click, move_to_element, move_to_element_with_offset, touch_move_to_element_with_offset, move_by_offset, drag_and_drop, drag_and_drop_by_offset, touch_drag_and_drop, touch_drag_by_offset, click_and_hold, long_press, release, send_keys, send_keys_to_element, key_down, key_up, pause
  • expected conditions: presence_of_element_located, visibility_of_element_located, element_to_be_clickable, invisibility_of_element_located, alert_is_present, title_is, title_contains, url_contains, url_to_be, url_matches, text checks, and window count checks

더 자세한 사용법은 GUIDE.md에 정리되어 있습니다.

License

This project is licensed under the GNU Affero General Public License v3.0.

selenodriver depends on nodriver, which is licensed under AGPL-3.0, so this project follows the same license family.

개발

python -m pip install -e ".[test]"
pytest

Run real browser smoke tests explicitly:

$env:SELENODRIVER_RUN_SMOKE='1'
pytest -m smoke

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

selenodriver-0.1.0.tar.gz (68.4 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

selenodriver-0.1.0-py3-none-any.whl (57.3 kB view details)

Uploaded Python 3

File details

Details for the file selenodriver-0.1.0.tar.gz.

File metadata

  • Download URL: selenodriver-0.1.0.tar.gz
  • Upload date:
  • Size: 68.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for selenodriver-0.1.0.tar.gz
Algorithm Hash digest
SHA256 063531d4ff8d6ad522a6e13db4652d15bbedba0e71838c8593d20fe06a835b6c
MD5 ae55c447b15e6818feb1303088738aff
BLAKE2b-256 3cc1d1bd7443803ab48625ec10c411ebea0f267376602b2be21918d803dcc9e7

See more details on using hashes here.

File details

Details for the file selenodriver-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: selenodriver-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 57.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.13.1

File hashes

Hashes for selenodriver-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 87d5eb9fd8153b90844ba332e183d61bdade9bbc67e95e24cbf9fbcceb1d62a7
MD5 40bad950e0b95fbf0755dd0e025e254e
BLAKE2b-256 b1b3e298c3146fd9228f2124e99c157e3b409bcf2224444ba680c6f87434cbf6

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page