Add archived/drissionpage-auto-login
This commit is contained in:
@@ -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.
|
||||
Reference in New Issue
Block a user