diff --git a/skills/archived/drissionpage-auto-login/SKILL.md b/skills/archived/drissionpage-auto-login/SKILL.md new file mode 100644 index 0000000..4341bae --- /dev/null +++ b/skills/archived/drissionpage-auto-login/SKILL.md @@ -0,0 +1,164 @@ +--- +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.