chore: улучшение архитектуры
This commit is contained in:
1 parent
0f60aa9046
commit
6b1935d78a
4 files changed
+82
-62
No files matched your search
Whitespace-only changes.
@@ -0,0 +1,47 @@
|
|||||||
|
from playwright.async_api import Page
|
||||||
|
|
||||||
|
from engine.schemas import ActionRequest
|
||||||
|
|
||||||
|
_actions: dict = {}
|
||||||
|
|
||||||
|
|
||||||
|
def register(fun) -> None:
|
||||||
|
_actions[fun.__name__] = fun
|
||||||
|
return fun
|
||||||
|
|
||||||
|
|
||||||
|
@register
|
||||||
|
async def fill(page: Page, act: ActionRequest) -> str | None:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register
|
||||||
|
async def mouse_move(page: Page, act: ActionRequest) -> str | None:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register
|
||||||
|
async def click(page: Page, act: ActionRequest) -> str | None:
|
||||||
|
...
|
||||||
|
|
||||||
|
|
||||||
|
@register
|
||||||
|
async def wait_for(page: Page, act: ActionRequest) -> str | None:
|
||||||
|
try:
|
||||||
|
assert act.selector
|
||||||
|
await page.wait_for_selector(act.selector, timeout=act.timeout * 1000)
|
||||||
|
except Exception as e:
|
||||||
|
return str(e)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
async def execute(page: Page, actions: list[ActionRequest]) -> list[str]:
|
||||||
|
actions_result = []
|
||||||
|
for act in actions:
|
||||||
|
try:
|
||||||
|
await _actions[act.type](page, act)
|
||||||
|
except Exception as e:
|
||||||
|
actions_result.append({"type": act.type, "ok": "false", "error": str(e)})
|
||||||
|
break
|
||||||
|
return actions_result
|
||||||
@@ -0,0 +1,17 @@
|
|||||||
|
from pydantic import BaseModel
|
||||||
|
|
||||||
|
|
||||||
|
class ActionRequest(BaseModel):
|
||||||
|
type: str
|
||||||
|
selector: str | None = None
|
||||||
|
value: str | None = None
|
||||||
|
timeout: int | None = None
|
||||||
|
|
||||||
|
|
||||||
|
class SolveRequest(BaseModel):
|
||||||
|
url: str
|
||||||
|
proxy: str
|
||||||
|
actions: list[ActionRequest]
|
||||||
|
timeout: int | None = None
|
||||||
|
screen: str = "1280x720"
|
||||||
|
user_agent: str | None = None
|
||||||
+18
-62
@@ -3,25 +3,10 @@ from datetime import datetime
|
|||||||
from camoufox.async_api import AsyncCamoufox
|
from camoufox.async_api import AsyncCamoufox
|
||||||
from fastapi import FastAPI
|
from fastapi import FastAPI
|
||||||
from fastapi import Request
|
from fastapi import Request
|
||||||
from playwright.async_api import Page
|
from playwright.async_api import ViewportSize, ProxySettings
|
||||||
from pydantic import BaseModel
|
|
||||||
|
|
||||||
|
from engine.schemas import SolveRequest
|
||||||
class ActionRequest(BaseModel):
|
from engine import actions
|
||||||
type: str
|
|
||||||
selector: str | None = None
|
|
||||||
value: str | None = None
|
|
||||||
timeout: int | None = None
|
|
||||||
|
|
||||||
|
|
||||||
class SolveRequest(BaseModel):
|
|
||||||
url: str
|
|
||||||
proxy: str
|
|
||||||
actions: list[ActionRequest]
|
|
||||||
timeout: int | None = None
|
|
||||||
screen: str | None = None
|
|
||||||
user_agent: str | None = None
|
|
||||||
captcha: str | None = None
|
|
||||||
|
|
||||||
|
|
||||||
app = FastAPI()
|
app = FastAPI()
|
||||||
@@ -32,56 +17,27 @@ async def root():
|
|||||||
return {"message": "Hello World"}
|
return {"message": "Hello World"}
|
||||||
|
|
||||||
|
|
||||||
async def _fill(page: "Page", act: ActionRequest) -> str | None:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
async def _mouse_move(page: "Page", act: ActionRequest) -> str | None:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
async def _click(page: "Page", act: ActionRequest) -> str | None:
|
|
||||||
...
|
|
||||||
|
|
||||||
|
|
||||||
async def _wait_for(page: Page, act: ActionRequest) -> str | None:
|
|
||||||
try:
|
|
||||||
assert act.selector
|
|
||||||
await page.wait_for_selector(act.selector, timeout=act.timeout * 1000)
|
|
||||||
except Exception as e:
|
|
||||||
return str(e)
|
|
||||||
else:
|
|
||||||
return None
|
|
||||||
|
|
||||||
|
|
||||||
@app.post("/v1/solve")
|
@app.post("/v1/solve")
|
||||||
async def solve(request: Request, payload: SolveRequest):
|
async def solve(request: Request, payload: SolveRequest):
|
||||||
api_key = request.headers.get('X-API-Key')
|
api_key = request.headers.get('X-API-Key')
|
||||||
async with AsyncCamoufox() as camoufo:
|
async with AsyncCamoufox() as camoufo:
|
||||||
page = await camoufo.new_page()
|
# TODO: настройка контекста
|
||||||
|
scr_w, scr_h = payload.screen.split("x")
|
||||||
|
scr_size = ViewportSize(width=int(scr_w), height=int(scr_h))
|
||||||
|
# TODO: распарс proxy-урл и заполнение объекта
|
||||||
|
# proxy = ProxySettings(socks5://host:port, username, password)
|
||||||
|
proxy = None
|
||||||
|
page = await camoufo.new_page(
|
||||||
|
user_agent=payload.user_agent,
|
||||||
|
proxy=proxy,
|
||||||
|
viewport=scr_size,
|
||||||
|
screen=scr_size,
|
||||||
|
)
|
||||||
page.set_default_timeout(30_000)
|
page.set_default_timeout(30_000)
|
||||||
await page.goto(url=payload.url)
|
await page.goto(url=payload.url)
|
||||||
actions_result = []
|
actions_result = await actions.execute(page, payload.actions)
|
||||||
status = True
|
status = not "error" in actions_result[-1]
|
||||||
error = None
|
error = ["Something error", None][status]
|
||||||
|
|
||||||
for act in payload.actions:
|
|
||||||
result = await {
|
|
||||||
"fill": _fill,
|
|
||||||
"mouse_move": _mouse_move,
|
|
||||||
"click": _click,
|
|
||||||
"wait_for": _wait_for,
|
|
||||||
}[act.type](page, act)
|
|
||||||
if( ok := result ) is None:
|
|
||||||
act_log = {"type": act.type, "ok": ok}
|
|
||||||
else:
|
|
||||||
act_log = {"type": act.type, "ok": ok, "error": result}
|
|
||||||
actions_result.append(act_log)
|
|
||||||
if "error" in act_log:
|
|
||||||
status = False
|
|
||||||
error = act_log["error"]
|
|
||||||
break
|
|
||||||
|
|
||||||
cookies = await camoufo.cookies()
|
cookies = await camoufo.cookies()
|
||||||
html = await page.inner_html('html')
|
html = await page.inner_html('html')
|
||||||
await page.screenshot(
|
await page.screenshot(
|
||||||
|
|||||||
Reference in new issue
Block a user