--- name: drissionpage-auto-login description: Automate login with DrissionPage — discover login pages, fill forms, solve CAPTCHAs with ddddocr, and verify success. tags: [drissionpage, automation, login, captcha, ddddocr, web-scraping] --- # DrissionPage Auto-Login with CAPTCHA Solving Automate login to web applications using DrissionPage, with automatic CAPTCHA solving via `ddddocr`. ## Setup ```bash python3 -m venv /tmp/drission_env && source /tmp/drission_env/bin/activate pip install DrissionPage ddddocr ``` ## Browser Configuration ```python from DrissionPage import ChromiumPage, ChromiumOptions import ddddocr import os import time co = ChromiumOptions() co.set_browser_path('/home/ubuntu/.cache/ms-playwright/chromium-1217/chrome-linux64/chrome') co.set_argument('--no-sandbox') co.set_argument('--disable-dev-shm-usage') co.set_argument('--disable-gpu') co.headless() co.auto_port() page = ChromiumPage(co) ``` ## Login Discovery Workflow When the login URL is unknown: 1. **Visit the homepage** and scan for login links: ```python page.get('https://www.example.com') time.sleep(3) links = page.eles('tag:a') for link in links: href = link.attr('href') or '' text = link.text.strip() if 'login' in href.lower() or 'login' in text.lower() or '登录' in text: print(f"Found: {text} -> {href}") ``` 2. **Common login URL patterns** to try: - `/login`, `/signin`, `/auth` - `login.example.com`, `passport.example.com`, `account.example.com` ## Form Filling ```python # Find inputs by name, placeholder, or type inputs = page.eles('css:input') for inp in inputs: itype = inp.attr('type') or 'text' name = inp.attr('name') or '' ph = inp.attr('placeholder') or '' if itype in ['text', 'email']: # Heuristic: match common username field indicators if any(kw in (name + ph).lower() for kw in ['phone', 'email', 'account', 'user', 'mobile', 'login']): inp.clear().input('your_username') elif itype == 'password': inp.clear().input('your_password') ``` ## CAPTCHA Solving with ddddocr ```python # 1. Find the CAPTCHA image element captcha_img = (page.ele('css:img.captcha') or page.ele('css:.captcha-img') or page.ele('xpath://img[contains(@src, "captcha")]')) if not captcha_img: captcha_input = page.ele('@name=captcha') if captcha_input: captcha_img = captcha_input.sibling('tag:img') # 2. Save the image (PITFALL: use a simple filename, NOT a directory path) # DrissionPage's save() may create a directory if the src URL looks like a path. # Always use a clean local filename. import shutil captcha_path = '/tmp/captcha_solve.jpg' if os.path.isdir(captcha_path): shutil.rmtree(captcha_path) # Use screenshot method instead of save() for reliability: captcha_img.get_screenshot(path=captcha_path) # 3. OCR recognition ocr = ddddocr.DdddOcr() with open(captcha_path, 'rb') as f: img_bytes = f.read() captcha_text = ocr.classification(img_bytes) print(f"CAPTCHA: {captcha_text}") # 4. Fill the captcha field page.ele('@name=captcha').clear().input(captcha_text) ``` ## Submit and Verify ```python # Click login button login_btn = page.ele('text:登录') or page.ele('text:Login') or page.ele('css:button[type=submit]') if login_btn: login_btn.click() else: page.press('Enter') time.sleep(5) # Verify success if 'dashboard' in page.url.lower() or 'main' in page.url.lower(): print("Login successful!") else: # Check for error messages body = page('tag:body').text if 'error' in body.lower() or '错误' in body: print("Login failed — check credentials or captcha") ``` ## Retry with CAPTCHA Refresh If the captcha is wrong, refresh and retry: ```python for attempt in range(3): # ... fill form and solve captcha ... login_btn.click() time.sleep(3) if 'error' not in page('tag:body').text.lower(): break # Click captcha image to refresh if captcha_img: captcha_img.click() time.sleep(1) else: page.refresh() time.sleep(2) ``` ## Pitfalls - **`save()` creates directories**: DrissionPage's `element.save(path)` may create a *directory* if the source URL contains path-like segments (e.g., `captcha.jpg;jsessionid=...`). Always use a clean local filename and check `os.path.isdir()` first. - **`get_screenshot()` is more reliable**: For single elements, `element.get_screenshot(path=...)` is more reliable than `save()`. - **uv-managed Python**: Use a temp venv to install packages. - **Headless + sandbox flags**: Always use `--no-sandbox --disable-dev-shm-usage --disable-gpu` and `co.headless()`. - **Auto port**: Use `co.auto_port()` to avoid conflicts. - **Wait times**: Add `time.sleep(2-5)` after page loads and form submissions for JS-rendered content. - **Iframe logins**: If inputs are inside iframes, switch context: `page = page.eles('tag:iframe')[0].child()`. - **Multiple hidden inputs**: Sites may have many hidden inputs. Filter by `type` and visible attributes. - **CAPTCHA case sensitivity**: Some sites require uppercase/lowercase matching. Try `captcha_text.upper()` or `.lower()` if login fails.