Improve KDocs QR capture
This commit is contained in:
@@ -268,24 +268,104 @@ class KDocsUploader:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def _capture_qr_image(self) -> Optional[bytes]:
|
def _capture_qr_image(self) -> Optional[bytes]:
|
||||||
candidates = [
|
pages = self._iter_pages()
|
||||||
self._page.locator("canvas"),
|
for page in pages:
|
||||||
self._page.locator("img[alt*='二维码']"),
|
for frame in page.frames:
|
||||||
self._page.locator("img[src*='qr']"),
|
target = self._find_qr_element_in_frame(frame)
|
||||||
]
|
if not target:
|
||||||
for locator in candidates:
|
continue
|
||||||
try:
|
try:
|
||||||
if locator.count() < 1:
|
|
||||||
continue
|
|
||||||
target = locator.first
|
|
||||||
target.wait_for(state="visible", timeout=5000)
|
|
||||||
return target.screenshot()
|
return target.screenshot()
|
||||||
except PlaywrightTimeoutError:
|
|
||||||
continue
|
|
||||||
except Exception:
|
except Exception:
|
||||||
continue
|
continue
|
||||||
|
for page in pages:
|
||||||
|
dialog_image = self._capture_dialog_image(page)
|
||||||
|
if dialog_image:
|
||||||
|
return dialog_image
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _iter_pages(self) -> list:
|
||||||
|
pages = []
|
||||||
|
if self._context:
|
||||||
|
pages.extend(self._context.pages)
|
||||||
|
if self._page and self._page not in pages:
|
||||||
|
pages.insert(0, self._page)
|
||||||
|
def rank(p) -> int:
|
||||||
|
url = (getattr(p, "url", "") or "").lower()
|
||||||
|
keywords = ("login", "account", "passport", "wechat", "qr")
|
||||||
|
return 0 if any(k in url for k in keywords) else 1
|
||||||
|
pages.sort(key=rank)
|
||||||
|
return pages
|
||||||
|
|
||||||
|
def _find_qr_element_in_frame(self, frame) -> Optional[Any]:
|
||||||
|
selectors = [
|
||||||
|
"canvas",
|
||||||
|
"img[alt*='二维码']",
|
||||||
|
"img[src*='qr']",
|
||||||
|
"img[src*='qrcode']",
|
||||||
|
"img[class*='qr']",
|
||||||
|
"canvas[class*='qr']",
|
||||||
|
"svg",
|
||||||
|
"div[role='img']",
|
||||||
|
]
|
||||||
|
best = None
|
||||||
|
best_score = None
|
||||||
|
for selector in selectors:
|
||||||
try:
|
try:
|
||||||
return self._page.screenshot(full_page=True)
|
locator = frame.locator(selector)
|
||||||
|
count = min(locator.count(), 20)
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
for i in range(count):
|
||||||
|
el = locator.nth(i)
|
||||||
|
try:
|
||||||
|
if not el.is_visible(timeout=800):
|
||||||
|
continue
|
||||||
|
box = el.bounding_box()
|
||||||
|
if not box:
|
||||||
|
continue
|
||||||
|
width = box.get("width", 0)
|
||||||
|
height = box.get("height", 0)
|
||||||
|
if width < 120 or height < 120 or width > 420 or height > 420:
|
||||||
|
continue
|
||||||
|
aspect_diff = abs(width - height)
|
||||||
|
if aspect_diff > 40:
|
||||||
|
continue
|
||||||
|
score = aspect_diff + abs(width - 260) + abs(height - 260)
|
||||||
|
if best_score is None or score < best_score:
|
||||||
|
best_score = score
|
||||||
|
best = el
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
return best
|
||||||
|
|
||||||
|
def _capture_dialog_image(self, page) -> Optional[bytes]:
|
||||||
|
selectors = "[role='dialog'], .dialog, .modal, .popup"
|
||||||
|
try:
|
||||||
|
dialogs = page.locator(selectors)
|
||||||
|
count = min(dialogs.count(), 6)
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
best = None
|
||||||
|
best_area = 0
|
||||||
|
for i in range(count):
|
||||||
|
el = dialogs.nth(i)
|
||||||
|
try:
|
||||||
|
if not el.is_visible(timeout=800):
|
||||||
|
continue
|
||||||
|
box = el.bounding_box()
|
||||||
|
if not box:
|
||||||
|
continue
|
||||||
|
area = box.get("width", 0) * box.get("height", 0)
|
||||||
|
if area > best_area:
|
||||||
|
best_area = area
|
||||||
|
best = el
|
||||||
|
except Exception:
|
||||||
|
continue
|
||||||
|
if not best:
|
||||||
|
return None
|
||||||
|
try:
|
||||||
|
return best.screenshot()
|
||||||
except Exception:
|
except Exception:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
@@ -317,7 +397,12 @@ class KDocsUploader:
|
|||||||
return {"success": True, "logged_in": True, "qr_image": ""}
|
return {"success": True, "logged_in": True, "qr_image": ""}
|
||||||
|
|
||||||
self._ensure_login_dialog()
|
self._ensure_login_dialog()
|
||||||
|
qr_image = None
|
||||||
|
for _ in range(5):
|
||||||
qr_image = self._capture_qr_image()
|
qr_image = self._capture_qr_image()
|
||||||
|
if qr_image:
|
||||||
|
break
|
||||||
|
time.sleep(1)
|
||||||
if not qr_image:
|
if not qr_image:
|
||||||
self._last_error = "二维码获取失败"
|
self._last_error = "二维码获取失败"
|
||||||
return {"success": False, "error": self._last_error}
|
return {"success": False, "error": self._last_error}
|
||||||
|
|||||||
Reference in New Issue
Block a user