Spaces:
Running
Running
Upload main.py
Browse files
main.py
CHANGED
|
@@ -63,9 +63,9 @@ _cache_ttl_yt = 1800
|
|
| 63 |
SHORTS_FALLBACK = [
|
| 64 |
{"id":"nqlLH6chLRo","title":"Tin nóng VTV Nam Bộ | #shorts","channel":"vtvnambo"},
|
| 65 |
{"id":"E7Kq0v3hG6w","title":"VTV Nam Bộ - Tin tức miền Nam | #shorts","channel":"vtvnambo"},
|
| 66 |
-
{"id":"Lu_iCQ5YwNM","title":"Công an lập
|
| 67 |
{"id":"CwWvijF8BOA","title":"Chú rể Ninh Bình bật khóc nhận món quà bí mật người cha quá cố gửi 26 năm trước","channel":"baodantri7941"},
|
| 68 |
-
{"id":"tvPewsc2ph4","title":"Tính năng
|
| 69 |
{"id":"b1Nxzv9ixlU","title":"Y án 3 năm tù với nữ tài xế uống 8 lon bia lái xe tông chủ tịch xã tử vong","channel":"baodantri7941"},
|
| 70 |
{"id":"Xp5eTwAZAis","title":"Người đánh hàng xóm tại chung cư ở Hà Nội bị tuyên hơn 4 tháng tù","channel":"baodantri7941"},
|
| 71 |
{"id":"Htzvwg6iOBM","title":"Xe điện Audi S6 Sportback e-tron có gì đặc biệt?","channel":"baodantri7941"},
|
|
@@ -75,24 +75,24 @@ SHORTS_FALLBACK = [
|
|
| 75 |
{"id":"VAfgNNgZDRs","title":"Khởi tố 4 đối tượng ném bom xăng vào nhà dân ở Đồng Nai","channel":"baodantri7941"},
|
| 76 |
{"id":"sBH_-zGh0Xw","title":"Vì sao Times New Roman vẫn nổi tiếng sau hàng chục năm?","channel":"baodantri7941"},
|
| 77 |
{"id":"woKn5f2bLHM","title":"Quảng Ninh ngập sâu diện rộng sau đợt mưa lớn","channel":"baodantri7941"},
|
| 78 |
-
{"id":"bcpgRoxbLPw","title":"Giông lốc quật bay mái tôn
|
| 79 |
{"id":"ZIIC5osy544","title":"Bé trai Trung Quốc rơi từ tầng 11 vẫn sống sót kỳ diệu","channel":"baodantri7941"},
|
| 80 |
-
{"id":"uTMJ49NQpyc","title":"Sau lớp mascot 40kg Câu chuyện mưu sinh của người
|
| 81 |
-
{"id":"7Pd6vZ2Lz1M","title":"Hành động ấm lòng của người đàn ông tìm kiếm 5 học sinh tử vong
|
| 82 |
{"id":"SlHLt_ZyPiE","title":"Xử phạt người đàn ông xóa số điện thoại cứu hộ trên cao tốc Bắc Nam","channel":"baosuckhoedoisongboyte"},
|
| 83 |
-
{"id":"IUOprcJyYr4","title":"Phụ nữ táo bón có phải do lười
|
| 84 |
-
{"id":"YY8ojFNE-AU","title":"Quái xế tự quay clip
|
| 85 |
{"id":"OV7_oGdQGII","title":"Bố cô dâu khóc sụt sùi rồi quẩy cực sung gây bão mạng","channel":"baosuckhoedoisongboyte"},
|
| 86 |
-
{"id":"FoxhFyz2skY","title":"Người đàn ông nước ngoài đập phá ô tô bẻ cần gạt nước ở Đà
|
| 87 |
-
{"id":"R1oC_I8dFPU","title":"Thanh niên buông tay lái đứng trên xe máy khi đổ đèo ở
|
| 88 |
-
{"id":"U0Ft6ChWAIo","title":"Cô giáo kể phút tháo chạy
|
| 89 |
{"id":"hH0ANeze_4E","title":"Liên tiếp hàng chục con bò bị sét đánh chết trong ngày mưa dông","channel":"baosuckhoedoisongboyte"},
|
| 90 |
{"id":"pXWt0QbAzRQ","title":"Va chạm giao thông người phụ nữ lăng mạ tài xế ô tô","channel":"baosuckhoedoisongboyte"},
|
| 91 |
-
{"id":"UWWLPY1OYt4","title":"CSGT
|
| 92 |
{"id":"AxhVTQutsuo","title":"Xuất tinh sớm và những hiểu lầm thường gặp","channel":"baosuckhoedoisongboyte"},
|
| 93 |
{"id":"cNy6FgaNxYM","title":"Cô dâu khóc sưng mắt vì 6 chỉ vàng không cánh mày bay trong ngày cưới","channel":"baosuckhoedoisongboyte"},
|
| 94 |
{"id":"IDt_S6q59Ro","title":"Chở bạn gái không đội mũ bảo hiểm thanh niên đấm CSGT","channel":"baosuckhoedoisongboyte"},
|
| 95 |
-
{"id":"LFxJ9Ik6W0A","title":"Mệnh lệnh từ trái tim CSGT Hà Nội
|
| 96 |
]
|
| 97 |
for _v in SHORTS_FALLBACK:
|
| 98 |
_v.setdefault("link", "https://www.youtube.com/watch?v="+_v["id"])
|
|
@@ -119,10 +119,10 @@ def _short_default(): return {"views":0,"likes":0,"shares":0,"comments":[]}
|
|
| 119 |
PRIORITY_LEAGUES = ["Ngoại Hạng Anh","FA Cup","Champions League","LaLiga","Copa del Rey","Serie A","Bundesliga","Ligue 1","V-League"]
|
| 120 |
LEAGUE_IDS = {"nha":27110,"laliga":27233,"seriea":27044,"bundesliga":26891,"ligue1":27212}
|
| 121 |
HL_LEAGUES = {
|
| 122 |
-
"premier-league":{"path":"anh/premier-league","name":"Premier League","emoji":"
|
| 123 |
-
"fa-cup":{"path":"anh/fa-cup","name":"FA Cup","emoji":"
|
| 124 |
"bundesliga":{"path":"duc/bundesliga","name":"Bundesliga","emoji":"🇩🇪"},
|
| 125 |
-
"serie-a":{"path":"italy/serie-a","name":"Serie A","emoji":"🇮
|
| 126 |
"la-liga":{"path":"tay-ban-nha/la-liga","name":"La Liga","emoji":"🇪🇸"},
|
| 127 |
"champions-league":{"path":"cup-chau-au/uefa-champions-league","name":"Champions League","emoji":"⭐"},
|
| 128 |
"europa-league":{"path":"cup-chau-au/uefa-europa-league","name":"Europa League","emoji":"🟠"},
|
|
@@ -222,7 +222,7 @@ def proxy_img(url: str = Query(...)):
|
|
| 222 |
def _scrape_xemlaibongda_page(page_path, limit=20):
|
| 223 |
"""
|
| 224 |
Scrape video từ xemlaibongda.top - Simple & Reliable
|
| 225 |
-
Dùng logic cũ đã test, không fetch
|
| 226 |
"""
|
| 227 |
try:
|
| 228 |
url = f"https://xemlaibongda.top/{page_path}" if page_path else "https://xemlaibongda.top/"
|
|
@@ -242,7 +242,7 @@ def _scrape_xemlaibongda_page(page_path, limit=20):
|
|
| 242 |
if not href.startswith("http"):
|
| 243 |
href = "https://xemlaibongda.top" + href
|
| 244 |
|
| 245 |
-
#
|
| 246 |
clean_href = href.split("?")[0].split("#")[0]
|
| 247 |
if clean_href in seen:
|
| 248 |
continue
|
|
@@ -312,7 +312,7 @@ def _scrape_xemlaibongda_page(page_path, limit=20):
|
|
| 312 |
if text and len(text) >= 5:
|
| 313 |
title = text[:100]
|
| 314 |
|
| 315 |
-
# Fallback: tạo title
|
| 316 |
if not title or len(title) < 3:
|
| 317 |
slug = clean_href.split("/video/")[-1].rstrip("/").split("/xem-lai/")[-1].rstrip("/")
|
| 318 |
title = slug.replace("-", " ").replace("_", " ").title()
|
|
@@ -342,7 +342,7 @@ def _scrape_xemlaibongda_page(page_path, limit=20):
|
|
| 342 |
return []
|
| 343 |
|
| 344 |
def _extract_img_src(a_tag):
|
| 345 |
-
"""Extract image URL từ
|
| 346 |
img = a_tag.find("img")
|
| 347 |
if not img and a_tag.parent:
|
| 348 |
img = a_tag.parent.find("img")
|
|
@@ -418,7 +418,7 @@ def _extract_title(a_tag, href):
|
|
| 418 |
if alt and len(alt) >= 3:
|
| 419 |
return alt
|
| 420 |
|
| 421 |
-
# 4. Thử text content của <a> (loại
|
| 422 |
text = a_tag.get_text(" ", strip=True)
|
| 423 |
if text and len(text) >= 3:
|
| 424 |
# Lấy dòng đầu tiên nếu có nhiều dòng
|
|
@@ -504,30 +504,24 @@ def _yt_channel_shorts_requests(channel, count=15):
|
|
| 504 |
except: return []
|
| 505 |
|
| 506 |
def scrape_shorts():
|
| 507 |
-
|
| 508 |
-
|
| 509 |
-
|
| 510 |
-
|
| 511 |
-
|
| 512 |
-
|
| 513 |
-
|
| 514 |
-
|
| 515 |
-
|
| 516 |
-
|
| 517 |
-
|
| 518 |
-
|
| 519 |
-
|
| 520 |
-
|
| 521 |
-
|
| 522 |
-
|
| 523 |
-
|
| 524 |
-
|
| 525 |
-
|
| 526 |
-
# Cache the result
|
| 527 |
-
_cache["yt_shorts_v3"] = {"d": vids, "t": time.time()}
|
| 528 |
-
_cache["yt_shorts_fallback"] = {"d": vids, "t": time.time()}
|
| 529 |
-
|
| 530 |
-
return vids
|
| 531 |
|
| 532 |
# ===== VTV NAM BO & WC SHORTS - using yt-dlp =====
|
| 533 |
from yt_scraper import get_vtvnambo_shorts, get_wc_related_shorts
|
|
@@ -731,7 +725,7 @@ def api_bdp_videos():
|
|
| 731 |
return JSONResponse(_cached("bdp_videos",_f))
|
| 732 |
|
| 733 |
# ===== NEWS =====
|
| 734 |
-
VNE_CATS={"thoi-su":("https://vnexpress.net/thoi-su","Thời Sự"),"the-gioi":("https://vnexpress.net/the-gioi","Thế Giới"),"kinh-doanh":("https://vnexpress.net/kinh-doanh","Kinh Doanh"),"the-thao":("https://vnexpress.net/the-thao","Thể Thao"),"giai-tri":("https://vnexpress.net/giai-tri","Giải Trí"),"suc-khoe":("https://vnexpress.net/suc-khoe","
|
| 735 |
|
| 736 |
def scrape_vne(cat_url):
|
| 737 |
try:
|
|
|
|
| 63 |
SHORTS_FALLBACK = [
|
| 64 |
{"id":"nqlLH6chLRo","title":"Tin nóng VTV Nam Bộ | #shorts","channel":"vtvnambo"},
|
| 65 |
{"id":"E7Kq0v3hG6w","title":"VTV Nam Bộ - Tin tức miền Nam | #shorts","channel":"vtvnambo"},
|
| 66 |
+
{"id":"Lu_iCQ5YwNM","title":"Công an lập h� sơ xử lý người phụ nữ chửi bới tát nam tài xế ô tô � Hà Nội","channel":"baodantri7941"},
|
| 67 |
{"id":"CwWvijF8BOA","title":"Chú rể Ninh Bình bật khóc nhận món quà bí mật người cha quá cố gửi 26 năm trước","channel":"baodantri7941"},
|
| 68 |
+
{"id":"tvPewsc2ph4","title":"Tính năng �n trên iPhone giúp giảm m�i m�t","channel":"baodantri7941"},
|
| 69 |
{"id":"b1Nxzv9ixlU","title":"Y án 3 năm tù với nữ tài xế uống 8 lon bia lái xe tông chủ tịch xã tử vong","channel":"baodantri7941"},
|
| 70 |
{"id":"Xp5eTwAZAis","title":"Người đánh hàng xóm tại chung cư ở Hà Nội bị tuyên hơn 4 tháng tù","channel":"baodantri7941"},
|
| 71 |
{"id":"Htzvwg6iOBM","title":"Xe điện Audi S6 Sportback e-tron có gì đặc biệt?","channel":"baodantri7941"},
|
|
|
|
| 75 |
{"id":"VAfgNNgZDRs","title":"Khởi tố 4 đối tượng ném bom xăng vào nhà dân ở Đồng Nai","channel":"baodantri7941"},
|
| 76 |
{"id":"sBH_-zGh0Xw","title":"Vì sao Times New Roman vẫn nổi tiếng sau hàng chục năm?","channel":"baodantri7941"},
|
| 77 |
{"id":"woKn5f2bLHM","title":"Quảng Ninh ngập sâu diện rộng sau đợt mưa lớn","channel":"baodantri7941"},
|
| 78 |
+
{"id":"bcpgRoxbLPw","title":"Giông lốc quật bay mái tôn � TP.HCM","channel":"baodantri7941"},
|
| 79 |
{"id":"ZIIC5osy544","title":"Bé trai Trung Quốc rơi từ tầng 11 vẫn sống sót kỳ diệu","channel":"baodantri7941"},
|
| 80 |
+
{"id":"uTMJ49NQpyc","title":"Sau lớp mascot 40kg Câu chuyện mưu sinh của người tr� ở TPHCM","channel":"baodantri7941"},
|
| 81 |
+
{"id":"7Pd6vZ2Lz1M","title":"Hành động ấm lòng của người đàn ông tìm kiếm 5 học sinh tử vong � sông Lô","channel":"baosuckhoedoisongboyte"},
|
| 82 |
{"id":"SlHLt_ZyPiE","title":"Xử phạt người đàn ông xóa số điện thoại cứu hộ trên cao tốc Bắc Nam","channel":"baosuckhoedoisongboyte"},
|
| 83 |
+
{"id":"IUOprcJyYr4","title":"Phụ nữ táo bón có phải do lười �n rau?","channel":"baosuckhoedoisongboyte"},
|
| 84 |
+
{"id":"YY8ojFNE-AU","title":"Quái xế tự quay clip n�t pô đánh võng đăng TikTok bị xử lý","channel":"baosuckhoedoisongboyte"},
|
| 85 |
{"id":"OV7_oGdQGII","title":"Bố cô dâu khóc sụt sùi rồi quẩy cực sung gây bão mạng","channel":"baosuckhoedoisongboyte"},
|
| 86 |
+
{"id":"FoxhFyz2skY","title":"Người đàn ông nước ngoài đập phá ô tô bẻ cần gạt nước ở Đà N�ng","channel":"baosuckhoedoisongboyte"},
|
| 87 |
+
{"id":"R1oC_I8dFPU","title":"Thanh niên buông tay lái đứng trên xe máy khi đổ đèo ở Đ�k L�k","channel":"baosuckhoedoisongboyte"},
|
| 88 |
+
{"id":"U0Ft6ChWAIo","title":"Cô giáo kể phút tháo chạy kh�i xe khách trước khi bị l� vò nát ở Cao Bằng","channel":"baosuckhoedoisongboyte"},
|
| 89 |
{"id":"hH0ANeze_4E","title":"Liên tiếp hàng chục con bò bị sét đánh chết trong ngày mưa dông","channel":"baosuckhoedoisongboyte"},
|
| 90 |
{"id":"pXWt0QbAzRQ","title":"Va chạm giao thông người phụ nữ lăng mạ tài xế ô tô","channel":"baosuckhoedoisongboyte"},
|
| 91 |
+
{"id":"UWWLPY1OYt4","title":"CSGT ch�n xe khách khống chế đối tượng cướp dây chuyền tại Gia Lai","channel":"baosuckhoedoisongboyte"},
|
| 92 |
{"id":"AxhVTQutsuo","title":"Xuất tinh sớm và những hiểu lầm thường gặp","channel":"baosuckhoedoisongboyte"},
|
| 93 |
{"id":"cNy6FgaNxYM","title":"Cô dâu khóc sưng mắt vì 6 chỉ vàng không cánh mày bay trong ngày cưới","channel":"baosuckhoedoisongboyte"},
|
| 94 |
{"id":"IDt_S6q59Ro","title":"Chở bạn gái không đội mũ bảo hiểm thanh niên đấm CSGT","channel":"baosuckhoedoisongboyte"},
|
| 95 |
+
{"id":"LFxJ9Ik6W0A","title":"Mệnh lệnh từ trái tim CSGT Hà Nội m� đường đưa bé 5 tháng tuổi đi cấp c�u","channel":"baosuckhoedoisongboyte"},
|
| 96 |
]
|
| 97 |
for _v in SHORTS_FALLBACK:
|
| 98 |
_v.setdefault("link", "https://www.youtube.com/watch?v="+_v["id"])
|
|
|
|
| 119 |
PRIORITY_LEAGUES = ["Ngoại Hạng Anh","FA Cup","Champions League","LaLiga","Copa del Rey","Serie A","Bundesliga","Ligue 1","V-League"]
|
| 120 |
LEAGUE_IDS = {"nha":27110,"laliga":27233,"seriea":27044,"bundesliga":26891,"ligue1":27212}
|
| 121 |
HL_LEAGUES = {
|
| 122 |
+
"premier-league":{"path":"anh/premier-league","name":"Premier League","emoji":"�������"},
|
| 123 |
+
"fa-cup":{"path":"anh/fa-cup","name":"FA Cup","emoji":"�"},
|
| 124 |
"bundesliga":{"path":"duc/bundesliga","name":"Bundesliga","emoji":"🇩🇪"},
|
| 125 |
+
"serie-a":{"path":"italy/serie-a","name":"Serie A","emoji":"🇮�"},
|
| 126 |
"la-liga":{"path":"tay-ban-nha/la-liga","name":"La Liga","emoji":"🇪🇸"},
|
| 127 |
"champions-league":{"path":"cup-chau-au/uefa-champions-league","name":"Champions League","emoji":"⭐"},
|
| 128 |
"europa-league":{"path":"cup-chau-au/uefa-europa-league","name":"Europa League","emoji":"🟠"},
|
|
|
|
| 222 |
def _scrape_xemlaibongda_page(page_path, limit=20):
|
| 223 |
"""
|
| 224 |
Scrape video từ xemlaibongda.top - Simple & Reliable
|
| 225 |
+
Dùng logic cũ đã test, không fetch t�ng trang (tránh timeout)
|
| 226 |
"""
|
| 227 |
try:
|
| 228 |
url = f"https://xemlaibongda.top/{page_path}" if page_path else "https://xemlaibongda.top/"
|
|
|
|
| 242 |
if not href.startswith("http"):
|
| 243 |
href = "https://xemlaibongda.top" + href
|
| 244 |
|
| 245 |
+
# B� query params
|
| 246 |
clean_href = href.split("?")[0].split("#")[0]
|
| 247 |
if clean_href in seen:
|
| 248 |
continue
|
|
|
|
| 312 |
if text and len(text) >= 5:
|
| 313 |
title = text[:100]
|
| 314 |
|
| 315 |
+
# Fallback: tạo title t� slug
|
| 316 |
if not title or len(title) < 3:
|
| 317 |
slug = clean_href.split("/video/")[-1].rstrip("/").split("/xem-lai/")[-1].rstrip("/")
|
| 318 |
title = slug.replace("-", " ").replace("_", " ").title()
|
|
|
|
| 342 |
return []
|
| 343 |
|
| 344 |
def _extract_img_src(a_tag):
|
| 345 |
+
"""Extract image URL từ th� <a> và parent elements"""
|
| 346 |
img = a_tag.find("img")
|
| 347 |
if not img and a_tag.parent:
|
| 348 |
img = a_tag.parent.find("img")
|
|
|
|
| 418 |
if alt and len(alt) >= 3:
|
| 419 |
return alt
|
| 420 |
|
| 421 |
+
# 4. Thử text content của <a> (loại b� quá dài)
|
| 422 |
text = a_tag.get_text(" ", strip=True)
|
| 423 |
if text and len(text) >= 3:
|
| 424 |
# Lấy dòng đầu tiên nếu có nhiều dòng
|
|
|
|
| 504 |
except: return []
|
| 505 |
|
| 506 |
def scrape_shorts():
|
| 507 |
+
vids=[]
|
| 508 |
+
with ThreadPoolExecutor(3) as ex:
|
| 509 |
+
futs=[ex.submit(_yt_channel_shorts_requests,ch,24) for ch in ["baodantri7941","baosuckhoedoisongboyte","vtvnambo"]]
|
| 510 |
+
for f in as_completed(futs):
|
| 511 |
+
try:
|
| 512 |
+
r=f.result()
|
| 513 |
+
if r: vids.extend(r)
|
| 514 |
+
except: pass
|
| 515 |
+
merged=[]; seen=set()
|
| 516 |
+
for v in vids:
|
| 517 |
+
vid=v.get("id")
|
| 518 |
+
if not vid or vid in seen: continue
|
| 519 |
+
seen.add(vid); merged.append(v)
|
| 520 |
+
for v in SHORTS_FALLBACK:
|
| 521 |
+
vid=v.get("id")
|
| 522 |
+
if not vid or vid in seen: continue
|
| 523 |
+
seen.add(vid); merged.append(v)
|
| 524 |
+
return merged[:60]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 525 |
|
| 526 |
# ===== VTV NAM BO & WC SHORTS - using yt-dlp =====
|
| 527 |
from yt_scraper import get_vtvnambo_shorts, get_wc_related_shorts
|
|
|
|
| 725 |
return JSONResponse(_cached("bdp_videos",_f))
|
| 726 |
|
| 727 |
# ===== NEWS =====
|
| 728 |
+
VNE_CATS={"thoi-su":("https://vnexpress.net/thoi-su","Thời Sự"),"the-gioi":("https://vnexpress.net/the-gioi","Thế Giới"),"kinh-doanh":("https://vnexpress.net/kinh-doanh","Kinh Doanh"),"the-thao":("https://vnexpress.net/the-thao","Thể Thao"),"giai-tri":("https://vnexpress.net/giai-tri","Giải Trí"),"suc-khoe":("https://vnexpress.net/suc-khoe","S�c Kh�e"),"phap-luat":("https://vnexpress.net/phap-luat","Pháp Luật"),"giao-duc":("https://vnexpress.net/giao-duc","Giáo Dục"),"du-lich":("https://vnexpress.net/du-lich","Du Lịch"),"doi-song":("https://vnexpress.net/doi-song","Đời Sống")}
|
| 729 |
|
| 730 |
def scrape_vne(cat_url):
|
| 731 |
try:
|