Skip to content

Commit a631769

Browse files
[投稿] 添加脚本: 谷歌热点新闻 — by 爬虫专家
1 parent 384c6f2 commit a631769

1 file changed

Lines changed: 227 additions & 0 deletions

File tree

Lines changed: 227 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,227 @@
1+
#!/usr/bin/env python3
2+
# -*- coding: utf-8 -*-
3+
4+
"""
5+
爬取谷歌热点新闻
6+
使用 RSS 订阅源获取最新新闻
7+
"""
8+
9+
import requests
10+
import xml.etree.ElementTree as ET
11+
import time
12+
from datetime import datetime
13+
import sys
14+
15+
def fetch_google_news(rss_url="https://news.google.com/rss?hl=zh-CN&gl=CN&ceid=CN:zh-Hans"):
16+
"""
17+
从 Google News RSS 订阅源获取热点新闻
18+
19+
Args:
20+
rss_url (str): Google News RSS 订阅源 URL
21+
22+
Returns:
23+
list: 新闻条目列表,每个条目包含标题、链接、发布时间等信息
24+
"""
25+
print("正在获取谷歌热点新闻...")
26+
27+
try:
28+
# 设置请求头,模拟浏览器访问
29+
headers = {
30+
'User-Agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 15_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/15.0 Mobile/15E148 Safari/604.1'
31+
}
32+
33+
# 发送请求获取 RSS 数据
34+
response = requests.get(rss_url, headers=headers, timeout=10)
35+
response.raise_for_status() # 检查请求是否成功
36+
37+
# 解析 XML
38+
root = ET.fromstring(response.content)
39+
40+
# XML 命名空间处理
41+
namespaces = {
42+
'atom': 'http://www.w3.org/2005/Atom',
43+
'content': 'http://purl.org/rss/1.0/modules/content/',
44+
'dc': 'http://purl.org/dc/elements/1.1/',
45+
'media': 'http://search.yahoo.com/mrss/'
46+
}
47+
48+
# 查找所有 item 元素
49+
items = root.findall('.//item')
50+
51+
if not items:
52+
# 尝试另一种查找方式
53+
items = root.findall('.//channel/item')
54+
55+
if not items:
56+
print("未获取到新闻条目")
57+
return []
58+
59+
print(f"成功获取到 {len(items)} 条新闻\n")
60+
61+
# 提取新闻信息
62+
news_items = []
63+
for i, item in enumerate(items[:20], 1): # 限制显示前20条
64+
# 获取标题
65+
title_elem = item.find('title')
66+
title = title_elem.text if title_elem is not None else '无标题'
67+
68+
# 获取链接
69+
link_elem = item.find('link')
70+
link = link_elem.text if link_elem is not None else '#'
71+
72+
# 获取发布时间
73+
pub_date_elem = item.find('pubDate')
74+
if pub_date_elem is None:
75+
pub_date_elem = item.find('dc:date', namespaces)
76+
published = pub_date_elem.text if pub_date_elem is not None else ''
77+
78+
# 获取描述/摘要
79+
desc_elem = item.find('description')
80+
if desc_elem is None:
81+
desc_elem = item.find('content:encoded', namespaces)
82+
summary = ''
83+
if desc_elem is not None and desc_elem.text:
84+
summary = desc_elem.text[:200]
85+
86+
# 获取来源
87+
source_elem = item.find('source')
88+
source = source_elem.text if source_elem is not None else ''
89+
90+
# 构建新闻项
91+
news_item = {
92+
'index': i,
93+
'title': title,
94+
'link': link,
95+
'published': published,
96+
'summary': summary,
97+
'source': source
98+
}
99+
news_items.append(news_item)
100+
101+
return news_items
102+
103+
except requests.RequestException as e:
104+
print(f"网络请求失败: {e}")
105+
return []
106+
except ET.ParseError as e:
107+
print(f"XML 解析失败: {e}")
108+
return []
109+
except Exception as e:
110+
print(f"获取新闻失败: {e}")
111+
return []
112+
113+
def display_news(news_items):
114+
"""格式化显示新闻"""
115+
if not news_items:
116+
print("没有新闻可显示")
117+
return
118+
119+
print("=" * 80)
120+
print(f"📰 谷歌热点新闻 ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})")
121+
print("=" * 80)
122+
123+
for item in news_items:
124+
print(f"\n{item['index']}. {item['title']}")
125+
126+
if item['source']:
127+
print(f" 来源: {item['source']}")
128+
129+
if item['published']:
130+
# 发布时间可能包含时间格式信息,直接显示
131+
print(f" 时间: {item['published']}")
132+
133+
if item['summary']:
134+
print(f" 摘要: {item['summary']}...")
135+
136+
print(f" 链接: {item['link']}")
137+
print("-" * 60)
138+
139+
def get_news_by_category():
140+
"""按类别获取新闻"""
141+
categories = {
142+
'1': ('综合', 'https://news.google.com/rss?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
143+
'2': ('国际', 'https://news.google.com/rss/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRGx1YlY4U0JYQjBMVUpTR2dKQ1VpZ0FQAQ?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
144+
'3': ('科技', 'https://news.google.com/rss/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRGRqTVhZU0JXVnVMVWRDR2dKQ1VpZ0FQAQ?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
145+
'4': ('商业', 'https://news.google.com/rss/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRGx6TVdZU0JXVnVMVWRDR2dKQ1VpZ0FQAQ?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
146+
'5': ('娱乐', 'https://news.google.com/rss/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNREpxYW5RU0JXVnVMVWRDR2dKQ1VpZ0FQAQ?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
147+
'6': ('体育', 'https://news.google.com/rss/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNRFp1ZEdvU0JXVnVMVWRDR2dKQ1VpZ0FQAQ?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
148+
'7': ('健康', 'https://news.google.com/rss/topics/CAAqKggKIiRDQkFTRlFvSUwyMHZNR3QwTlRFU0JXVnVMVWRDR2dKQ1VpZ0FQAQ?hl=zh-CN&gl=CN&ceid=CN:zh-Hans'),
149+
}
150+
151+
print("\n请选择新闻类别:")
152+
for key, (name, _) in categories.items():
153+
print(f" {key}. {name}")
154+
print(" 0. 综合新闻 (默认)")
155+
156+
choice = input("\n请输入数字选择类别 (默认: 0): ").strip()
157+
158+
if choice in categories:
159+
category_name, rss_url = categories[choice]
160+
print(f"\n正在获取「{category_name}」类别新闻...")
161+
return rss_url
162+
else:
163+
print("\n正在获取综合新闻...")
164+
return categories['1'][1] # 默认返回综合新闻 URL
165+
166+
def main():
167+
"""主函数"""
168+
print("=" * 80)
169+
print("📰 谷歌热点新闻爬取工具")
170+
print("=" * 80)
171+
172+
# 获取用户选择的类别
173+
rss_url = get_news_by_category()
174+
175+
# 获取新闻
176+
news_items = fetch_google_news(rss_url)
177+
178+
# 显示新闻
179+
if news_items:
180+
display_news(news_items)
181+
182+
# 保存到文件选项
183+
save_option = input("\n是否将新闻保存到文件? (y/N): ").strip().lower()
184+
if save_option == 'y':
185+
save_to_file(news_items)
186+
else:
187+
print("未能获取到新闻,请检查网络连接或稍后重试")
188+
189+
def save_to_file(news_items):
190+
"""将新闻保存到文件"""
191+
timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
192+
filename = f"谷歌新闻_{timestamp}.txt"
193+
194+
try:
195+
with open(filename, 'w', encoding='utf-8') as f:
196+
f.write("=" * 80 + "\n")
197+
f.write(f"谷歌热点新闻 ({datetime.now().strftime('%Y-%m-%d %H:%M:%S')})\n")
198+
f.write("=" * 80 + "\n\n")
199+
200+
for item in news_items:
201+
f.write(f"{item['index']}. {item['title']}\n")
202+
203+
if item['source']:
204+
f.write(f" 来源: {item['source']}\n")
205+
206+
if item['published']:
207+
f.write(f" 时间: {item['published']}\n")
208+
209+
if item['summary']:
210+
f.write(f" 摘要: {item['summary']}...\n")
211+
212+
f.write(f" 链接: {item['link']}\n")
213+
f.write("-" * 60 + "\n\n")
214+
215+
print(f"✓ 新闻已保存到文件: {filename}")
216+
except Exception as e:
217+
print(f"✗ 保存文件失败: {e}")
218+
219+
if __name__ == "__main__":
220+
try:
221+
main()
222+
except KeyboardInterrupt:
223+
print("\n\n程序被用户中断")
224+
sys.exit(0)
225+
except Exception as e:
226+
print(f"\n程序执行出错: {e}")
227+
sys.exit(1)

0 commit comments

Comments
 (0)