VNEWS / bongda_proxy.py
bep40's picture
Squash main
4b6e868
Raw
History Blame Contribute Delete
4.92 kB
"""VNEWS — Bongda Proxy Endpoint (for fast match detail loading)"""
import requests
from bs4 import BeautifulSoup
import re
import json
def _cl(s):
return re.sub(r'\s+', ' ', str(s or '')).strip()
def _normalize_time(raw):
t = _cl(raw)
t = re.sub(r"(\d+)'\s*\+(\d+)", r"\1+\2'", t)
t = t.replace("''", "'")
return t
def scrape_match_html(event_id, url=None):
result = {"event_id": event_id, "found": False, "sections": []}
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
"Referer": "https://bongda.com.vn/",
}
html = None
urls_to_try = [url] if url else []
urls_to_try += [
f"https://bongda.com.vn/tran-dau/{event_id}/centre/",
f"https://bongda.com.vn/tran-dau/{event_id}/preview/",
]
for u in urls_to_try:
if not u:
continue
try:
resp = requests.get(u, headers=headers, timeout=15, allow_redirects=True)
if resp.status_code == 200 and len(resp.text) > 1000:
html = resp.text
break
except Exception:
continue
if not html:
return result
try:
soup = BeautifulSoup(html, 'html.parser')
info = {}
tel = soup.select_one('.teams')
if tel:
he = tel.select_one('.team.home')
if he:
ne = he.select_one('p:not(.logo)') or he.find('p')
if ne: info['home_team'] = _cl(ne.get_text())
lo = he.select_one('img')
if lo: info['home_logo'] = lo.get('src', '')
ae = tel.select_one('.team.away')
if ae:
ne = ae.select_one('p:not(.logo)') or ae.find('p')
if ne: info['away_team'] = _cl(ne.get_text())
lo = ae.select_one('img')
if lo: info['away_logo'] = lo.get('src', '')
sc = tel.select_one('.score')
if sc:
parts = [_cl(p.get_text()) for p in sc.select('p')]
if len(parts) >= 2: info['score'] = f"{parts[0]} - {parts[1]}"
lb = sc.select_one('.label')
if lb: info['status_label'] = _cl(lb.get_text())
if info.get('home_team') and info.get('away_team'):
result['info'] = info
result['found'] = True
result['sections'].append('info')
else:
return result
events = []
events_div = soup.select_one('.events')
if events_div:
period = ''
for child in events_div.children:
if not hasattr(child, 'name') or not child.name: continue
cls = ' '.join(child.get('class', []))
if 'period' in cls:
h2 = child.find('h2')
if h2: period = _cl(h2.get_text())
for ev in child.children:
if not hasattr(ev, 'name') or not ev.name: continue
ev_cls = ' '.join(ev.get('class', []))
if 'event' not in ev_cls: continue
ev_data = {'team': 'home' if 'home' in ev_cls else 'away', 'period': period, 'type': 'unknown', 'time': ''}
type_el = ev.select_one('.event-type')
if type_el:
if type_el.select_one('[class*="redcard"]'): ev_data['type'] = 'redcard'
elif type_el.select_one('[class*="yellowcard"]'): ev_data['type'] = 'yellowcard'
elif type_el.select_one('[class*="goal"]'): ev_data['type'] = 'goal'
elif type_el.select_one('[class*="substitution"]'): ev_data['type'] = 'substitution'
players_el = ev.select_one('.players')
if players_el:
time_el = players_el.select_one('.event-time')
if time_el: ev_data['time'] = _normalize_time(time_el.get_text())
text = _cl(players_el.get_text(' ', strip=True).replace(ev_data['time'], '').strip())
ev_data['players'] = text
events.append(ev_data)
if events:
result['events'] = events
result['sections'].append('events')
except Exception as e:
result['error'] = str(e)
return result
from fastapi import Query
from fastapi.responses import JSONResponse
def add_bongda_proxy_endpoint(app):
@app.get('/api/proxy/bongda')
def proxy_bongda(event_id: int = Query(default=None), url: str = Query(default=None)):
if event_id is None:
return JSONResponse({'error': 'event_id required'}, status_code=400)
return JSONResponse(scrape_match_html(event_id, url))