Hana Celeste commited on
Commit
60d5394
·
verified ·
1 Parent(s): 168aac6

Update main.py

Browse files
Files changed (1) hide show
  1. main.py +35 -19
main.py CHANGED
@@ -1,6 +1,7 @@
1
  import asyncio
2
  import requests
3
  import time
 
4
  from fastapi import FastAPI
5
  from playwright.async_api import async_playwright
6
 
@@ -8,7 +9,6 @@ app = FastAPI()
8
 
9
  IMGBB_API_KEY = "093dee93ec19418d26cc76f40e053725"
10
 
11
- # --- HELPER: KHỞI TẠO TRÌNH DUYỆT VỚI TÙY CHỌN TỐI ƯU ---
12
  async def get_page(uid: str, fast_mode=False):
13
  p = await async_playwright().start()
14
  browser = await p.chromium.launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'])
@@ -18,20 +18,17 @@ async def get_page(uid: str, fast_mode=False):
18
  )
19
  page = await context.new_page()
20
 
21
- # NẾU LÀ FAST MODE (CHỈ LẤY TEXT), CHẶN TẢI ẢNH VÀ CSS ĐỂ TĂNG TỐC
22
  if fast_mode:
 
23
  await page.route("**/*", lambda route: route.abort() if route.request.resource_type in ["image", "media", "font", "stylesheet"] else route.continue_())
24
 
25
  url = f"https://enka.network/u/{uid}/"
26
  await page.goto(url, wait_until="domcontentloaded", timeout=60000)
27
  return browser, page
28
 
29
- # --- ENDPOINTS ---
30
-
31
  @app.get("/info")
32
  async def info(uid: str):
33
  start_time = time.time()
34
- # Sử dụng Fast Mode để lấy thông tin text cực nhanh
35
  browser, page = await get_page(uid, fast_mode=True)
36
  try:
37
  data = await page.evaluate("""
@@ -50,10 +47,24 @@ async def info(uid: str):
50
  wl = wlMatch ? wlMatch[1] : null;
51
  }
52
 
53
- const stats = Array.from(document.querySelectorAll('tr.stat')).map(tr => ({
54
- value: tr.querySelector('td:first-child')?.innerText.trim(),
55
- label: tr.querySelector('td:last-child')?.innerText.trim()
56
- }));
 
 
 
 
 
 
 
 
 
 
 
 
 
 
57
 
58
  const characters = Array.from(document.querySelectorAll('.CharacterList .avatar')).map(el => {
59
  const figure = el.querySelector('figure.chara');
@@ -72,25 +83,27 @@ async def info(uid: str):
72
  }
73
  """)
74
  await browser.close()
75
- execution_time = f"{round(time.time() - start_time, 2)}s"
76
- return {"execution_time": execution_time, "uid": uid, **data}
 
 
 
77
  except Exception as e:
78
  await browser.close()
79
- return {"execution_time": f"{round(time.time() - start_time, 2)}s", "error": str(e)}
80
 
81
  @app.get("/gen")
82
  async def generate(uid: str, char: str = None):
83
  start_time = time.time()
84
- # Không dùng fast_mode vì cần tải CSS/Ảnh để render Card
85
  browser, page = await get_page(uid, fast_mode=False)
86
  try:
87
  if char:
88
- formatted_char = char.strip().capitalize()
89
  char_selector = f"//div[contains(@class, 'avatar')]//figure[contains(@style, '{formatted_char}')]"
90
  try:
91
  await page.wait_for_selector(char_selector, timeout=5000)
92
  await page.click(char_selector)
93
- await asyncio.sleep(1)
94
  except: pass
95
 
96
  await page.click('button[data-icon="image"]')
@@ -110,12 +123,15 @@ async def generate(uid: str, char: str = None):
110
  """)
111
  await browser.close()
112
  res = requests.post("https://api.imgbb.com/1/upload", data={"key": IMGBB_API_KEY, "image": img_base64})
113
- execution_time = f"{round(time.time() - start_time, 2)}s"
114
- return {"execution_time": execution_time, "uid": uid, "char": char or "default", "card_url": res.json().get('data', {}).get('url')}
 
 
 
115
  except Exception as e:
116
  await browser.close()
117
- return {"execution_time": f"{round(time.time() - start_time, 2)}s", "error": str(e)}
118
 
119
  @app.get("/")
120
  def home():
121
- return {"status": "Enka API Optimized"}
 
1
  import asyncio
2
  import requests
3
  import time
4
+ import re
5
  from fastapi import FastAPI
6
  from playwright.async_api import async_playwright
7
 
 
9
 
10
  IMGBB_API_KEY = "093dee93ec19418d26cc76f40e053725"
11
 
 
12
  async def get_page(uid: str, fast_mode=False):
13
  p = await async_playwright().start()
14
  browser = await p.chromium.launch(headless=True, args=['--no-sandbox', '--disable-setuid-sandbox', '--disable-dev-shm-usage'])
 
18
  )
19
  page = await context.new_page()
20
 
 
21
  if fast_mode:
22
+ # Chỉ cho phép tải tài nguyên cần thiết cho Text, chặn ảnh/css nặng
23
  await page.route("**/*", lambda route: route.abort() if route.request.resource_type in ["image", "media", "font", "stylesheet"] else route.continue_())
24
 
25
  url = f"https://enka.network/u/{uid}/"
26
  await page.goto(url, wait_until="domcontentloaded", timeout=60000)
27
  return browser, page
28
 
 
 
29
  @app.get("/info")
30
  async def info(uid: str):
31
  start_time = time.time()
 
32
  browser, page = await get_page(uid, fast_mode=True)
33
  try:
34
  data = await page.evaluate("""
 
47
  wl = wlMatch ? wlMatch[1] : null;
48
  }
49
 
50
+ // FETCH STATS CÙNG ICON URL
51
+ const stats = Array.from(document.querySelectorAll('tr.stat')).map(tr => {
52
+ const val = tr.querySelector('td:first-child')?.innerText.trim();
53
+ const label = tr.querySelector('td:last-child')?.innerText.trim();
54
+ const iconTd = tr.querySelector('td.icon');
55
+ let iconUrl = null;
56
+
57
+ if (iconTd) {
58
+ const style = iconTd.getAttribute('style');
59
+ // Regex bóc tách link từ --icon: url(...)
60
+ const match = style.match(/url\\(["']?(.*?)["']?\\)/);
61
+ if (match && match[1]) {
62
+ iconUrl = "https://enka.network" + match[1].replace(/\\\\/g, "");
63
+ }
64
+ }
65
+
66
+ return { value: val, label: label, icon: iconUrl };
67
+ });
68
 
69
  const characters = Array.from(document.querySelectorAll('.CharacterList .avatar')).map(el => {
70
  const figure = el.querySelector('figure.chara');
 
83
  }
84
  """)
85
  await browser.close()
86
+ return {
87
+ "execution_time": f"{round(time.time() - start_time, 2)}s",
88
+ "uid": uid,
89
+ **data
90
+ }
91
  except Exception as e:
92
  await browser.close()
93
+ return {"error": str(e)}
94
 
95
  @app.get("/gen")
96
  async def generate(uid: str, char: str = None):
97
  start_time = time.time()
 
98
  browser, page = await get_page(uid, fast_mode=False)
99
  try:
100
  if char:
101
+ formatted_char = char.strip().capitalize();
102
  char_selector = f"//div[contains(@class, 'avatar')]//figure[contains(@style, '{formatted_char}')]"
103
  try:
104
  await page.wait_for_selector(char_selector, timeout=5000)
105
  await page.click(char_selector)
106
+ await asyncio.sleep(1)
107
  except: pass
108
 
109
  await page.click('button[data-icon="image"]')
 
123
  """)
124
  await browser.close()
125
  res = requests.post("https://api.imgbb.com/1/upload", data={"key": IMGBB_API_KEY, "image": img_base64})
126
+ return {
127
+ "execution_time": f"{round(time.time() - start_time, 2)}s",
128
+ "uid": uid,
129
+ "card_url": res.json().get('data', {}).get('url')
130
+ }
131
  except Exception as e:
132
  await browser.close()
133
+ return {"error": str(e)}
134
 
135
  @app.get("/")
136
  def home():
137
+ return {"status": "Enka API Pro is Live"}