前言:信息焦虑是每个从业者的痛点
作为一名 AI/云技术从业者,我每天需要关注大量行业动态:竞品更新、技术博客、新产品发布、政策变化...手动去各个网站浏览不仅耗时,而且容易遗漏重要信息。
直到我搭建了这套爬虫 + 大模型自动摘要系统,每天早上只需要 5 分钟就能了解全行业动态,信息获取效率提升至少 5 倍。
今天分享这套系统的完整搭建方案,从爬虫到 AI 摘要,一条龙打通。
系统架构概览
数据源网站 → 爬虫脚本 → 内容清洗 → 大模型API → 结构化摘要 → 邮件/飞书推送
核心组件:
- 爬虫:Python + requests + BeautifulSoup(轻量级)或 Playwright(动态页面)
- 内容清洗:正则 + BeautifulSoup 提取正文
- 大模型:OpenAI GPT-4 / 阿里通义千问 / 百度文心一言
- 定时任务:Linux cron 或 Windows 任务计划程序
- 推送渠道:邮件、飞书群机器人、企业微信
第一步:搭建爬虫框架
目标网站列表
根据我们关注的方向,爬取以下类型网站:
# config.py
import os
# 环境变量配置
OPENAI_API_KEY = os.getenv("OPENAI_API_KEY")
DASHSCOPE_API_KEY = os.getenv("DASHSCOPE_API_KEY") # 通义千问
# 爬取目标配置
CRAWL_TARGETS = {
"ai_news": [
{"name": "机器之心", "url": "https://www.jiqizhixin.com/", "selector": "article"},
{"name": "量子位", "url": "https://www.qbitai.com/", "selector": ".article-list a"},
{"name": "36氪AI", "url": "https://36kr.com/category/ai", "selector": ".article-item"},
],
"cloud_news": [
{"name": "阿里云公告", "url": "https://help.aliyun.com/", "selector": ".article-item"},
{"name": "腾讯云公告", "url": "https://cloud.tencent.com/document/news", "selector": ".news-item"},
],
"industry_news": [
{"name": "大河网科技", "url": "https://tech.dahe.cn/", "selector": "article"},
]
}
爬虫核心代码
# crawler.py
import requests
from bs4 import BeautifulSoup
from datetime import datetime
from typing import List, Dict
import hashlib
class NewsCrawler:
def __init__(self, timeout=30):
self.headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36"
}
self.timeout = timeout
def fetch_page(self, url: str) -> str:
"""获取页面内容"""
try:
response = requests.get(url, headers=self.headers, timeout=self.timeout)
response.raise_for_status()
return response.text
except requests.RequestException as e:
print(f"请求失败 {url}: {e}")
return ""
def extract_articles(self, html: str, selector: str) -> List[Dict]:
"""提取文章列表"""
soup = BeautifulSoup(html, "html.parser")
articles = []
for item in soup.select(selector)[:10]: # 限制数量
title_elem = item.select_one("h2, h3, .title, a")
link_elem = item.select_one("a")
desc_elem = item.select_one("p, .desc, .summary")
if title_elem and link_elem:
title = title_elem.get_text(strip=True)
link = link_elem.get("href", "")
# 补全相对链接
if link and not link.startswith("http"):
link = "https://example.com" + link
articles.append({
"title": title,
"url": link,
"source": item.get("data-source", ""),
"publish_time": datetime.now().isoformat()
})
return articles
def extract_content(self, url: str) -> str:
"""提取文章正文"""
html = self.fetch_page(url)
if not html:
return ""
soup = BeautifulSoup(html, "html.parser")
# 移除无关标签
for tag in soup.find_all(["script", "style", "nav", "footer", "aside"]):
tag.decompose()
# 提取正文
content = soup.select_one("article, .article-content, .post-content, main")
if content:
return content.get_text(separator="\n", strip=True)[:3000] # 限制长度
return ""
def deduplicate(self, articles: List[Dict]) -> List[Dict]:
"""基于URL去重"""
seen = set()
unique = []
for article in articles:
url_hash = hashlib.md5(article["url"].encode()).hexdigest()
if url_hash not in seen:
seen.add(url_hash)
unique.append(article)
return unique
第二步:大模型生成摘要
摘要提示词模板
好的提示词是生成高质量摘要的关键:
# prompt_template.py
SUMMARY_PROMPT = """
你是一位专业的科技资讯编辑。请为以下文章生成一篇精炼的摘要。
## 要求:
1. 摘要长度:150-300字
2. 必须包含:文章核心观点、关键技术点、潜在影响
3. 语气:专业但易懂,适合技术从业者阅读
4. 格式:分段清晰,重点信息用**加粗**
## 文章标题:
{title}
## 文章正文:
{content}
## 输出格式:
【一句话总结】:xxx
【核心内容】:xxx
【技术要点】:xxx
【影响分析】:xxx
"""
# 用于生成多条资讯的日报汇总
DAILY_REPORT_PROMPT = """
你是一位科技行业分析师。请根据以下资讯列表,生成一份今日行业日报。
## 要求:
1. 按主题分类整理
2. 每类选取最重要的3条
3. 标注信息来源
4. 总字数:500-800字
## 今日资讯:
{articles}
## 输出格式:
# 今日AI/云技术行业日报
## 日期:{date}
### 一、大模型与AI动态
...
### 二、云计算与云服务
...
### 三、行业趋势分析
...
"""
摘要生成代码
# summarizer.py
import openai
import dashscope
from typing import List, Dict
class Summarizer:
def __init__(self, provider="dashscope"):
self.provider = provider
if provider == "openai":
openai.api_key = os.getenv("OPENAI_API_KEY")
elif provider == "dashscope":
dashscope.api_key = os.getenv("DASHSCOPE_API_KEY")
def summarize_article(self, title: str, content: str) -> str:
"""单篇文章摘要"""
prompt = SUMMARY_PROMPT.format(title=title, content=content)
if self.provider == "openai":
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
elif self.provider == "dashscope":
response = dashscope.Generation.call(
model="qwen-max",
prompt=prompt,
temperature=0.3
)
return response.output.text
def generate_daily_report(self, articles: List[Dict]) -> str:
"""生成日报"""
articles_text = "\n\n".join([
f"【{a['title']}】\n来源: {a['source']}\n链接: {a['url']}\n摘要: {a.get('summary', 'N/A')}"
for a in articles[:20] # 限制数量
])
prompt = DAILY_REPORT_PROMPT.format(
articles=articles_text,
date=datetime.now().strftime("%Y年%m月%d日")
)
if self.provider == "openai":
response = openai.chat.completions.create(
model="gpt-4o",
messages=[{"role": "user", "content": prompt}],
temperature=0.3
)
return response.choices[0].message.content
elif self.provider == "dashscope":
response = dashscope.Generation.call(
model="qwen-max",
prompt=prompt,
temperature=0.3
)
return response.output.text
第三步:定时任务与推送
定时执行脚本
# main.py
import json
from datetime import datetime
from crawler import NewsCrawler
from summarizer import Summarizer
from notifier import Notifier
def main():
print(f"[{datetime.now()}] 开始抓取...")
# 1. 初始化组件
crawler = NewsCrawler()
summarizer = Summarizer(provider="dashscope")
notifier = Notifier()
all_articles = []
# 2. 遍历爬取所有目标
for category, targets in CRAWL_TARGETS.items():
for target in targets:
html = crawler.fetch_page(target["url"])
if html:
articles = crawler.extract_articles(html, target["selector"])
all_articles.extend(articles)
print(f" ✓ {target['name']}: {len(articles)} 篇")
# 3. 去重
all_articles = crawler.deduplicate(all_articles)
print(f"去重后: {len(all_articles)} 篇")
# 4. 生成摘要(可并行加速)
for article in all_articles[:15]: # 限制处理数量
content = crawler.extract_content(article["url"])
if content:
article["summary"] = summarizer.summarize_article(
article["title"],
content
)
# 5. 生成日报
daily_report = summarizer.generate_daily_report(all_articles)
# 6. 推送
notifier.send_email(daily_report)
notifier.send_feishu(daily_report)
# 7. 保存历史记录
with open(f"daily_report_{datetime.now().strftime('%Y%m%d')}.json", "w", encoding="utf-8") as f:
json.dump({
"date": datetime.now().isoformat(),
"articles": all_articles,
"report": daily_report
}, f, ensure_ascii=False, indent=2)
print(f"[{datetime.now()}] 完成!")
if __name__ == "__main__":
main()
飞书群推送
# notifier.py
import requests
import smtplib
from email.mime.text import MIMEText
from email.header import Header
class Notifier:
def __init__(self):
self.feishu_webhook = os.getenv("FEISHU_WEBHOOK")
def send_feishu(self, content: str):
"""飞书群机器人推送"""
if not self.feishu_webhook:
return
payload = {
"msg_type": "text",
"content": {"text": content}
}
response = requests.post(
self.feishu_webhook,
json=payload
)
return response.json()
def send_email(self, content: str, recipients: List[str] = None):
"""邮件推送"""
if recipients is None:
recipients = os.getenv("EMAIL_RECIPIENTS", "").split(",")
msg = MIMEText(content, "html", "utf-8")
msg["Subject"] = Header(f"【日报】AI/云技术行业动态 {datetime.now().strftime('%Y-%m-%d')}", "utf-8")
with smtplib.SMTP_SSL("smtp.gmail.com", 465) as server:
server.login(os.getenv("EMAIL_USER"), os.getenv("EMAIL_PASSWORD"))
server.sendmail(os.getenv("EMAIL_USER"), recipients, msg.as_string())
设置定时任务
Linux (crontab):
# 每天早上8点执行
0 8 * * * cd /path/to/project && /usr/bin/python3 main.py >> /var/log/crawler.log 2>&1
Windows (任务计划程序):
# 创建每日任务
schtasks /create /tn "AI资讯日报" /tr "python.exe C:\path\to\main.py" /sc daily /st 08:00
效果展示
使用这套系统后,我的日常工作流程变成了:
| 环节 | 之前 | 之后 |
|---|---|---|
| 信息浏览 | 1.5小时/天 | 5分钟/天 |
| 关键信息筛选 | 30分钟/天 | 0 |
| 行业动态了解 | 碎片化、不系统 | 系统化、每日汇总 |
| 竞品跟踪 | 容易遗漏 | 全面覆盖 |
实际输出示例:
【日报】AI/云技术行业动态 2026-04-17
一、大模型与AI动态
- OpenAI发布GPT-5 Turbo,上下文窗口扩展至200K,支持多模态输入...
- 阿里云百炼平台上线新功能,支持自定义模型微调...
二、云计算与云服务
- 腾讯云轻量应用服务器新增2个地域,郑州区域上线...
- AWS发布Graviton4实例,性价比提升40%...
进阶优化建议
1. 增加并行处理
from concurrent.futures import ThreadPoolExecutor
def summarize_parallel(self, articles: List[Dict], max_workers=5) -> List[Dict]:
with ThreadPoolExecutor(max_workers=max_workers) as executor:
futures = {
executor.submit(self.summarize_article, a["title"], a.get("content", "")): a
for a in articles
}
for future in futures:
article = futures[future]
try:
article["summary"] = future.result()
except Exception as e:
article["summary"] = f"摘要生成失败: {e}"
return articles
2. 添加去重与相似度过滤
使用向量数据库(如 Milvus)存储已处理内容,新文章先做相似度比对,避免重复推送。
3. 支持更多数据源
- 微信公众号(通过RSSHub)
- Twitter/X
- Reddit机器学习板块
- Hacker News
常见问题
Q: 爬虫被反爬了怎么办? A: 使用代理池 + 随机延时 + User-Agent轮换,或者改用RSSHub等现成的RSS转换服务。
Q: 大模型API费用高怎么办? A: 使用本地部署的 Ollama + Llama3,或切换到更便宜的国产模型(如通义千问、智谱GLM)。
Q: 如何处理动态渲染页面? A: 使用 Playwright 或 Selenium 来处理 JavaScript 渲染的内容。
总结
这套系统实现了:
- 自动化抓取:覆盖多个科技媒体,一键采集
- AI智能摘要:大模型生成结构化摘要,快速了解要点
- 定时推送:每天自动执行,无需人工干预
- 数据积累:历史记录可用于趋势分析
代码已上传 GitHub,有兴趣的朋友可以自行部署。有问题欢迎留言交流!
关于作者
长期关注大模型应用落地与云服务器实战,专注技术在企业场景中的落地实践。
个人博客:yunduancloud.icu —— 持续更新云计算、AI大模型实战教程,欢迎访问交流。