bep40 commited on
Commit
f2b9412
·
verified ·
1 Parent(s): 646a9f6

Thêm AI Việt Nam & AI Thế Giới ưu tiên hàng đầu, tin mới nhất mỗi ngày

Browse files
Files changed (1) hide show
  1. app_v2_entry.py +72 -0
app_v2_entry.py CHANGED
@@ -499,11 +499,83 @@ def _get_hot_topics():
499
  if is_dup:continue
500
  seen.add(key);topics.append({'label':'#'+re.sub(r'\s+','',display[key].title()),'topic':display[key],'count':count})
501
  if len(topics)>=20:break
 
 
 
 
502
  for kw in['World Cup 2026','Kinh tế Việt Nam','Bóng đá châu Âu','Công nghệ AI','Giá vàng','Thời tiết']:
503
  if len(topics)>=24:break
504
  if not any(kw.lower() in s for s in seen):topics.append({'label':'#'+re.sub(r'\s+','',kw.title()),'topic':kw,'count':0})
505
  _hot_cache.update({'t':now,'d':topics[:24]});return topics[:24]
506
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
507
  @app.get('/api/hot_topics')
508
  def api_hot_topics():
509
  resp = JSONResponse({'topics':_get_hot_topics()})
 
499
  if is_dup:continue
500
  seen.add(key);topics.append({'label':'#'+re.sub(r'\s+','',display[key].title()),'topic':display[key],'count':count})
501
  if len(topics)>=20:break
502
+ # ALWAYS pin AI topics FIRST (ưu tiên hiển thị)
503
+ ai_pinned = ['AI Việt Nam', 'AI Thế Giới']
504
+ for kw in reversed(ai_pinned):
505
+ topics.insert(0, {'label':'#'+re.sub(r'\s+','',kw).title(),'topic':kw,'count':999,'pinned':True,'ai':True})
506
  for kw in['World Cup 2026','Kinh tế Việt Nam','Bóng đá châu Âu','Công nghệ AI','Giá vàng','Thời tiết']:
507
  if len(topics)>=24:break
508
  if not any(kw.lower() in s for s in seen):topics.append({'label':'#'+re.sub(r'\s+','',kw.title()),'topic':kw,'count':0})
509
  _hot_cache.update({'t':now,'d':topics[:24]});return topics[:24]
510
 
511
+ # ===== AI NEWS: AI Việt Nam & AI Thế Giới =====
512
+ _ai_news_cache = {'t':0,'d':{'ai_vietnam':[],'ai_the_gioi':[],'all':[]}}
513
+
514
+ def _get_ai_news():
515
+ """Get AI news sorted by newest first. Returns two categories + combined all."""
516
+ now=time.time()
517
+ if _ai_news_cache['d']['all'] and now-_ai_news_cache['t']<600:return _ai_news_cache['d']
518
+
519
+ # AI Việt Nam: từ GenK (Công Nghệ), VnExpress, Dân Trí, VietNamNet
520
+ ai_vietnam=[]
521
+ try:
522
+ # GenK AI section
523
+ r=req.get("https://genk.vn/ai.chn",headers={'User-Agent':'Mozilla/5.0'},timeout=10)
524
+ if r.status_code==200:
525
+ r.encoding='utf-8';soup=BeautifulSoup(r.text,'lxml')
526
+ seen=set()
527
+ for a in soup.find_all('a',href=True):
528
+ href=a.get('href','')
529
+ if not href.endswith('.chn') or href=='/ai.chn':continue
530
+ if href.startswith('/'):href='https://genk.vn'+href
531
+ if href in seen:continue
532
+ title=a.get('title','') or a.get_text(strip=True)
533
+ if not title or len(title)<20:continue
534
+ seen.add(href)
535
+ img_src=''
536
+ container=a.parent
537
+ for _ in range(6):
538
+ if container is None:break
539
+ for img in container.find_all('img'):
540
+ s=img.get('data-src','') or img.get('src','')
541
+ if s and 'mediacdn' in s and 'avatar' not in s and 'logo' not in s:img_src=s;break
542
+ if img_src:break;container=container.parent
543
+ ai_vietnam.append({'title':title[:120],'url':href,'img':img_src,'via':'GenK','ai_category':'ai_vietnam','ai_label':'AI Việt Nam'})
544
+ if len(ai_vietnam)>=15:break
545
+ except:pass
546
+
547
+ # Thêm AI Việt Nam từ VnExpress + Dân Trí
548
+ for topic in ['trí tuệ nhân tạo','AI Việt Nam','trí tuệ nhân tạo việt nam']:
549
+ try:
550
+ for item in _s_vnexpress(topic,3):
551
+ if not any(x.get('url')==item['url'] for x in ai_vietnam):
552
+ item['ai_category']='ai_vietnam';item['ai_label']='AI Việt Nam'
553
+ ai_vietnam.append(item)
554
+ except:pass
555
+
556
+ # AI Thế Giới
557
+ ai_the_gioi=[];seen=set()
558
+ for topic in ['artificial intelligence','AI','machine learning','chatgpt','deep learning']:
559
+ for src_fn in[_s_vnexpress,_s_dantri,_s_vietnamnet]:
560
+ try:
561
+ for item in src_fn(topic,3):
562
+ if item.get('url') and item['url'] not in seen:
563
+ seen.add(item['url']);item['ai_category']='ai_the_gioi';item['ai_label']='AI Thế Giới'
564
+ ai_the_gioi.append(item)
565
+ except:pass
566
+ if len(ai_the_gioi)>=15:break
567
+
568
+ # Sort by newest first - we don't have dates, so just interleave
569
+ all_items=ai_vietnam+ai_the_gioi
570
+ result={'ai_vietnam':ai_vietnam[:20],'ai_the_gioi':ai_the_gioi[:20],'all':all_items[:30]}
571
+ _ai_news_cache.update({'t':now,'d':result});return result
572
+
573
+ @app.get('/api/ai_news')
574
+ def api_ai_news():
575
+ resp=JSONResponse(_get_ai_news())
576
+ resp.headers["Cache-Control"]="public, max-age=120"
577
+ return resp
578
+
579
  @app.get('/api/hot_topics')
580
  def api_hot_topics():
581
  resp = JSONResponse({'topics':_get_hot_topics()})