Sooteemon commited on
Commit
9d7be98
·
verified ·
1 Parent(s): bf00b84

Update scraper.py

Browse files
Files changed (1) hide show
  1. scraper.py +87 -38
scraper.py CHANGED
@@ -1,66 +1,97 @@
1
  import requests
2
- import feedparser # เราจะใช้ feedparser เป็นหลัก
3
- from urllib.parse import quote # ใช้สำหรับเข้ารหัส keyword
4
-
 
5
  # --- ไม่จำเป็นต้องใช้ BeautifulSoup อีกต่อไป ---
6
- # from bs4 import BeautifulSoup
7
  # import time
8
  # from datetime import datetime
9
 
10
  class YahooFinanceScraper:
11
  def __init__(self):
12
- # User-Agent ยังคงมีประโยชน์
13
  self.headers = {
14
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
15
  }
16
- # base_url ไม่จำเป็นต้องใช้อีกต่อไป
17
- # self.base_url = "https://finance.yahoo.com"
18
 
19
  def _parse_feed(self, url, max_articles=10):
20
- """ฟังก์ชันช่วยในการดึงและแปลง RSS feed"""
21
  news_list = []
 
22
  try:
23
- # feedparser สามารถรับ URL และ User-Agent ได้โดยตรง
 
 
 
24
  feed = feedparser.parse(url, agent=self.headers['User-Agent'])
25
-
26
- for entry in feed.entries[:max_articles]:
27
- news_list.append({
28
- 'title': entry.get('title', 'No title'),
29
- # ลิงก์จาก Google News RSS มักจะพาไปหน้า Google ก่อน เราจึงต้อง clean มัน
30
- 'link': entry.get('link', '').split('&url=')[-1],
31
- 'summary': entry.get('summary', '')[:300], # จำกัด 300 ตัวอักษร
32
- 'published': entry.get('published', 'N/A')
33
- })
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
34
  except Exception as e:
35
  print(f"Error parsing feed: {e}")
36
- return self._get_fallback_news(1) # ถ้าพัง ให้ไปที่ fallback
37
-
38
- return news_list
39
 
40
  def get_latest_news(self, symbol="", max_articles=10):
41
  """
42
  ดึงข่าวล่าสุดจาก Yahoo Finance (แก้ไขใหม่ให้ใช้ RSS เสมอ)
 
43
  """
44
  if symbol:
45
- # (เสถียร) ใช้ RSS feed สำหรับหุ้นนั้นๆ
46
  url = f"https://finance.yahoo.com/rss/quotes/{symbol.upper()}"
47
  else:
48
- # (เสถียร) ใช้ RSS feed ข่าวทั่วไป
49
  url = "https://finance.yahoo.com/news/rssindex"
50
-
51
  news_list = self._parse_feed(url, max_articles)
52
-
53
- # ถ้าดึงข่าวหุ้นแล้วไม่เจอ (เช่น พิมพ์ผิด) ให้ลอง fallback
54
  if symbol and not news_list:
55
  return self._get_fallback_news(max_articles)
56
-
57
  return news_list
58
 
59
  def _get_fallback_news(self, max_articles):
60
- """วิธีสำรองในกรณีที่ดึงข่าวไม่ได้ (ใช้ Top Stories feed)"""
 
 
 
61
  try:
62
  url = "https://finance.yahoo.com/rss/topstories"
63
- return self._parse_feed(url, max_articles)
64
  except:
65
  return [{
66
  'title': 'Unable to fetch news',
@@ -72,20 +103,38 @@ class YahooFinanceScraper:
72
  def search_news(self, keyword, max_articles=10):
73
  """
74
  ค้นหาข่าวด้วย keyword (แก้ไขใหม่ให้ใช้ Google News RSS ซึ่งเสถียรกว่ามาก)
 
75
  """
76
  if not keyword:
77
- return self.get_latest_news(max_articles=max_articles) # ถ้าไม่ใส่ keyword ก็ไปข่าวล่าสุด
78
-
79
  try:
80
- # (เสถียรมาก) ใช้ Google News RSS ค้นหาเฉพาะในเว็บ finance.yahoo.com
81
  safe_keyword = quote(keyword)
82
  url = f"https://news.google.com/rss/search?q={safe_keyword}+site:finance.yahoo.com&hl=en-US&gl=US&ceid=US:en"
83
-
84
- news_list = self._parse_feed(url, max_articles)
85
-
86
- # ถ้า Google News ค้นไม่เจอ ให้ลอง fallback
87
  return news_list if news_list else self._get_fallback_news(max_articles)
88
-
89
  except Exception as e:
90
  print(f"Search error: {e}")
91
- return self._get_fallback_news(max_articles)
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  import requests
2
+ import feedparser
3
+ from urllib.parse import quote
4
+ from datetime import datetime, timedelta, timezone # <--- เพิ่มใหม่
5
+ import calendar # <--- เพิ่มใหม่
6
  # --- ไม่จำเป็นต้องใช้ BeautifulSoup อีกต่อไป ---
7
+ # from bs4 import BeautifulSoup
8
  # import time
9
  # from datetime import datetime
10
 
11
  class YahooFinanceScraper:
12
  def __init__(self):
 
13
  self.headers = {
14
  'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36'
15
  }
 
 
16
 
17
  def _parse_feed(self, url, max_articles=10):
18
+ """ฟังก์ชันช่วยในการดึงและแปลง RSS feed (พร้อมกรอง 7 วันล่าสุด)"""
19
  news_list = []
20
+
21
  try:
22
+ # <--- เพิ่มใหม่: กำหนดเวลาตัดออก (7 วันย้อนหลัง)
23
+ # ใช้ .now(timezone.utc) เพื่อให้เป็นการเปรียบเทียบที่ถูกต้อง
24
+ cutoff_date_utc = datetime.now(timezone.utc) - timedelta(days=7)
25
+
26
  feed = feedparser.parse(url, agent=self.headers['User-Agent'])
27
+
28
+ # <--- แก้ไข: วนลูป feed.entries ทั้งหมดเพื่อค้นหาข่าวที่ตรงเงื่อนไข
29
+ for entry in feed.entries:
30
+
31
+ # <--- เพิ่มใหม่: ตรวจสอบและแปลงวันที่
32
+ published_struct = entry.get('published_parsed')
33
+ if not published_struct:
34
+ continue # ข้ามข่าวนี้ถ้าไม่มีวันที่ที่ parse ได้
35
+
36
+ try:
37
+ # feedparser ให้ published_parsed เป็น UTC struct_time
38
+ # เราต้องใช้ calendar.timegm เพื่อแปลงเป็น timestamp (UTC)
39
+ article_timestamp = calendar.timegm(published_struct)
40
+ article_date_utc = datetime.fromtimestamp(article_timestamp, tz=timezone.utc)
41
+ except Exception:
42
+ continue # ข้ามหากแปลงวันที่ไม่ได้
43
+
44
+ # <--- เพิ่มใหม่: ทำการกรองเวลา
45
+ if article_date_utc >= cutoff_date_utc:
46
+ # ถ้าข่าวนี้อยู่ในช่วง 7 วัน ให้เพิ่มลง list
47
+ news_list.append({
48
+ 'title': entry.get('title', 'No title'),
49
+ 'link': entry.get('link', '').split('&url=')[-1],
50
+ 'summary': entry.get('summary', '')[:300],
51
+ # ใช้ .isoformat() เพื่อเก็บวันที่ในรูปแบบมาตรฐาน
52
+ 'published': article_date_utc.isoformat()
53
+ })
54
+
55
+ # <--- เพิ่มใหม่: ถ้าได้ข่าวครบตามจำนวน max_articles แล้ว ให้หยุด
56
+ if len(news_list) >= max_articles:
57
+ break
58
+ else:
59
+ # <--- เพิ่มใหม่: (Optimization)
60
+ # ถ้าเจอข่าวที่เก่ากว่า 7 วัน ให้หยุดค้นหาต่อ
61
+ # (เพราะ RSS feed มักจะเรียงจากใหม่ไปเก่า)
62
+ break
63
+
64
  except Exception as e:
65
  print(f"Error parsing feed: {e}")
66
+ return self._get_fallback_news(1)
67
+
68
+ return news_list # คืนค่า list ที่กรองแล้ว
69
 
70
  def get_latest_news(self, symbol="", max_articles=10):
71
  """
72
  ดึงข่าวล่าสุดจาก Yahoo Finance (แก้ไขใหม่ให้ใช้ RSS เสมอ)
73
+ (ฟังก์ชันนี้ไม่ต้องแก้ เพราะ _parse_feed ถูกแก้แล้ว)
74
  """
75
  if symbol:
 
76
  url = f"https://finance.yahoo.com/rss/quotes/{symbol.upper()}"
77
  else:
 
78
  url = "https://finance.yahoo.com/news/rssindex"
79
+
80
  news_list = self._parse_feed(url, max_articles)
81
+
 
82
  if symbol and not news_list:
83
  return self._get_fallback_news(max_articles)
84
+
85
  return news_list
86
 
87
  def _get_fallback_news(self, max_articles):
88
+ """
89
+ วิธีสำรองในกรณีที่ดึงข่าวไม่ได้ (ใช้ Top Stories feed)
90
+ (ฟังก์ชันนี้จะถูกกรอง 7 วันโดยอัตโนมัติ เพราะเรียกใช้ _parse_feed)
91
+ """
92
  try:
93
  url = "https://finance.yahoo.com/rss/topstories"
94
+ return self._parse_feed(url, max_articles) # <--- จะถูกกรอง 7 วันอัตโนมัติ
95
  except:
96
  return [{
97
  'title': 'Unable to fetch news',
 
103
  def search_news(self, keyword, max_articles=10):
104
  """
105
  ค้นหาข่าวด้วย keyword (แก้ไขใหม่ให้ใช้ Google News RSS ซึ่งเสถียรกว่ามาก)
106
+ (ฟังก์ชันนี้จะถูกกรอง 7 วันโดยอัตโนมัติ เพราะเรียกใช้ _parse_feed)
107
  """
108
  if not keyword:
109
+ return self.get_latest_news(max_articles=max_articles)
110
+
111
  try:
 
112
  safe_keyword = quote(keyword)
113
  url = f"https://news.google.com/rss/search?q={safe_keyword}+site:finance.yahoo.com&hl=en-US&gl=US&ceid=US:en"
114
+
115
+ news_list = self._parse_feed(url, max_articles) # <--- จะถูกกรอง 7 วันอัตโนมัติ
116
+
 
117
  return news_list if news_list else self._get_fallback_news(max_articles)
118
+
119
  except Exception as e:
120
  print(f"Search error: {e}")
121
+ return self._get_fallback_news(max_articles)
122
+
123
+ # --- ตัวอย่างการใช้งาน (เหมือนเดิม) ---
124
+ if __name__ == '__main__':
125
+ scraper = YahooFinanceScraper()
126
+
127
+ print("--- ข่าวล่าสุด (ไม่ระบุสัญลักษณ์) (กรอง 7 วัน) ---")
128
+ latest_news = scraper.get_latest_news(max_articles=5)
129
+ for news in latest_news:
130
+ print(f"[{news['published']}] {news['title']}")
131
+
132
+ print("\n--- ข่าวหุ้น AAPL (กรอง 7 วัน) ---")
133
+ aapl_news = scraper.get_latest_news("AAPL", max_articles=5)
134
+ for news in aapl_news:
135
+ print(f"[{news['published']}] {news['title']}")
136
+
137
+ print("\n--- ค้นหาคำว่า 'NVIDIA' (กรอง 7 วัน) ---")
138
+ search_results = scraper.search_news("NVIDIA", max_articles=5)
139
+ for news in search_results:
140
+ print(f"[{news['published']}] {news['title']}")