Files
atomk-hermes-skills/skills/archived/drissionpage-auto-login/SKILL.md
T

165 lines
5.1 KiB
Markdown

---
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.