Python爬虫 + 大模型:自动抓取行业资讯并生成摘要,每天节省2小时信息筛选时间

3 阅读7分钟

前言:信息焦虑是每个从业者的痛点

作为一名 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动态

  1. OpenAI发布GPT-5 Turbo,上下文窗口扩展至200K,支持多模态输入...
  2. 阿里云百炼平台上线新功能,支持自定义模型微调...

二、云计算与云服务

  1. 腾讯云轻量应用服务器新增2个地域,郑州区域上线...
  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 渲染的内容。


总结

这套系统实现了:

  1. 自动化抓取:覆盖多个科技媒体,一键采集
  2. AI智能摘要:大模型生成结构化摘要,快速了解要点
  3. 定时推送:每天自动执行,无需人工干预
  4. 数据积累:历史记录可用于趋势分析

代码已上传 GitHub,有兴趣的朋友可以自行部署。有问题欢迎留言交流!


关于作者

长期关注大模型应用落地与云服务器实战,专注技术在企业场景中的落地实践。

个人博客:yunduancloud.icu —— 持续更新云计算、AI大模型实战教程,欢迎访问交流。