告别命令行恐惧:用Python写个自动摸鱼脚本,定时抓取新闻和基金数据(附源码)
用Python打造智能摸鱼助手定时抓取新闻与基金数据实战最近在技术社区看到一个有趣的讨论程序员如何在工作中高效摸鱼有人调侃说真正的高手不是逃避工作而是用技术让摸鱼变成自我提升。今天我们就来实践一个既实用又有趣的项目——用Python编写自动化摸鱼脚本定时抓取新闻和基金数据并通过桌面通知提醒。这个项目特别适合想要提升Python技能的开发者。通过requests、BeautifulSoup等库的实际应用你不仅能学到网页抓取技术还能掌握定时任务和桌面通知的实现方法。最重要的是整个过程完全合法合规不会涉及任何敏感操作。1. 环境准备与基础配置在开始编写摸鱼脚本前我们需要搭建好开发环境。推荐使用Python 3.8或更高版本这个版本在稳定性和新特性支持上达到了很好的平衡。首先安装必要的依赖库pip install requests beautifulsoup4 plyer schedule这些库各司其职requests用于发送HTTP请求获取网页内容beautifulsoup4解析HTML文档提取我们需要的数据plyer实现跨平台的桌面通知功能schedule设置定时任务让脚本自动运行如果你使用VSCode作为开发工具可以安装Python扩展来获得更好的开发体验。在扩展市场中搜索Python安装微软官方提供的那个版本即可。提示建议创建一个虚拟环境来管理项目依赖避免污染全局Python环境。可以使用python -m venv myenv命令创建。2. 新闻抓取功能实现新闻抓取是我们的核心功能之一。我们将从几个主流新闻网站获取头条新闻然后提取标题和摘要信息。2.1 分析新闻网站结构以某新闻网站为例我们可以通过浏览器开发者工具查看其HTML结构。按F12打开开发者工具找到新闻列表所在的HTML元素。通常新闻列表会包含在div或ul标签中每个新闻项可能有类似news-item的class。import requests from bs4 import BeautifulSoup def fetch_news(): url https://example-news-site.com/latest headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 } try: response requests.get(url, headersheaders, timeout10) response.raise_for_status() soup BeautifulSoup(response.text, html.parser) news_items [] for item in soup.select(.news-item): title item.select_one(.title).text.strip() summary item.select_one(.summary).text.strip() news_items.append({title: title, summary: summary}) return news_items except Exception as e: print(f获取新闻失败: {e}) return []2.2 处理反爬机制许多网站都有反爬虫措施我们需要做一些处理来避免被封禁设置合理的请求头模拟浏览器访问控制请求频率不要过于频繁使用代理IP如果需要大量抓取处理各种HTTP状态码和异常def safe_fetch(url, retry3): for i in range(retry): try: response requests.get(url, headers{ User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept-Language: zh-CN,zh;q0.9 }, timeout8) if response.status_code 200: return response elif response.status_code 429: time.sleep(10) # 被限流时等待 else: print(f请求失败状态码: {response.status_code}) except Exception as e: print(f请求异常: {e}) time.sleep(2) return None3. 基金数据抓取与分析除了新闻很多开发者还关心自己的基金收益。我们可以从基金平台抓取实时数据并做简单分析。3.1 获取基金实时数据基金数据通常通过API接口提供我们可以找到这些接口并模拟请求def fetch_fund_data(fund_code): api_url fhttps://api.example-fund.com/v3/fund/{fund_code} try: response requests.get(api_url, headers{ Referer: https://www.example-fund.com/ }, timeout5) data response.json() return { name: data[name], current: data[current_price], change: data[change_percent], time: data[update_time] } except Exception as e: print(f获取基金数据失败: {e}) return None3.2 基金数据分析与提醒我们可以设置一些条件当基金涨跌幅达到阈值时发送通知from plyer import notification def check_fund_alert(fund_data, threshold0.03): if not fund_data: return change float(fund_data[change].strip(%)) / 100 if abs(change) threshold: direction 上涨 if change 0 else 下跌 notification.notify( titlef基金{alert}: {fund_data[name]}, messagef当前价格: {fund_data[current]}{direction}{abs(change)*100:.2f}%, timeout10 )4. 定时任务与系统集成为了让脚本自动运行我们需要设置定时任务。Python的schedule库非常适合这种需求。4.1 设置定时任务import schedule import time def job(): print(开始执行摸鱼任务...) news fetch_news() if news: show_news_notification(news[0]) # 显示最新的一条新闻 fund_data fetch_fund_data(161725) # 以招商中证白酒为例 if fund_data: check_fund_alert(fund_data) # 每30分钟执行一次 schedule.every(30).minutes.do(job) while True: schedule.run_pending() time.sleep(1)4.2 系统托盘集成Windows示例对于更高级的集成我们可以让脚本运行在系统托盘中import sys from PyQt5.QtWidgets import QApplication, QSystemTrayIcon, QMenu from PyQt5.QtGui import QIcon app QApplication(sys.argv) tray QSystemTrayIcon(QIcon(fish.ico), parentapp) tray.setToolTip(智能摸鱼助手) menu QMenu() exit_action menu.addAction(退出) exit_action.triggered.connect(app.quit) tray.setContextMenu(menu) tray.show() # 在这里启动之前的定时任务循环5. 高级功能与优化基础功能实现后我们可以考虑添加一些增强功能让摸鱼体验更上一层楼。5.1 多源新闻聚合单一新闻源可能不够全面我们可以整合多个来源NEWS_SOURCES [ { name: 源A, url: https://news-a.com/latest, title_selector: .news-title, summary_selector: .description }, { name: 源B, url: https://api.news-b.com/v1/articles, is_api: True, title_key: title, summary_key: abstract } ] def fetch_multi_news(): all_news [] for source in NEWS_SOURCES: if source.get(is_api): data fetch_api_news(source) else: data fetch_html_news(source) all_news.extend(data) # 按时间排序 return sorted(all_news, keylambda x: x[time], reverseTrue)[:5]5.2 数据持久化与历史记录使用SQLite存储历史数据方便后续分析import sqlite3 from datetime import datetime def init_db(): conn sqlite3.connect(fish.db) c conn.cursor() c.execute(CREATE TABLE IF NOT EXISTS news (id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT, content TEXT, source TEXT, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)) c.execute(CREATE TABLE IF NOT EXISTS funds (id INTEGER PRIMARY KEY AUTOINCREMENT, code TEXT, name TEXT, price REAL, change REAL, timestamp DATETIME DEFAULT CURRENT_TIMESTAMP)) conn.commit() conn.close() def save_news(news_item): conn sqlite3.connect(fish.db) c conn.cursor() c.execute(INSERT INTO news (title, content, source) VALUES (?, ?, ?), (news_item[title], news_item[summary], example)) conn.commit() conn.close()5.3 可视化数据分析使用matplotlib生成简单的趋势图import matplotlib.pyplot as plt import pandas as pd def plot_fund_trend(fund_code, days7): conn sqlite3.connect(fish.db) df pd.read_sql(fSELECT date(timestamp) as date, price FROM funds WHERE code {fund_code} ORDER BY timestamp DESC LIMIT {days*24}, conn) conn.close() if not df.empty: df[date] pd.to_datetime(df[date]) daily_avg df.groupby(date)[price].mean() plt.figure(figsize(10, 5)) daily_avg.plot() plt.title(f基金{fund_code}近{days}日趋势) plt.xlabel(日期) plt.ylabel(价格) plt.grid() plt.savefig(fund_trend.png) plt.close()6. 安全与优化建议在开发这类自动化工具时有几个重要注意事项遵守robots.txt在抓取前检查目标网站的robots.txt文件尊重网站的爬虫政策设置合理间隔请求之间添加适当延迟避免对服务器造成负担错误处理完善异常处理确保脚本不会因为某个错误而完全停止工作资源管理及时关闭数据库连接和文件句柄避免资源泄漏用户代理使用合理的User-Agent标识你的爬虫# 良好的爬虫实践示例 def responsible_crawler(url): try: # 首先检查robots.txt robots_url /.join(url.split(/)[:3]) /robots.txt robots_resp requests.get(robots_url, timeout5) if robots_resp.status_code 200: from urllib.robotparser import RobotFileParser rp RobotFileParser() rp.parse(robots_resp.text.splitlines()) if not rp.can_fetch(*, url): print(f根据robots.txt不允许抓取: {url}) return None # 添加随机延迟 time.sleep(random.uniform(1, 3)) # 设置合理的请求头 headers { User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64), Accept-Encoding: gzip, deflate, Connection: keep-alive } response requests.get(url, headersheaders, timeout8) response.raise_for_status() return response.text except Exception as e: print(f抓取过程中出错: {e}) return None7. 完整代码结构与部署将所有功能模块整合后我们的项目结构如下smart-fish/ ├── main.py # 主程序入口 ├── config.py # 配置文件 ├── news_crawler.py # 新闻抓取模块 ├── fund_crawler.py # 基金数据模块 ├── notification.py # 通知功能 ├── scheduler.py # 定时任务 ├── db/ # 数据库文件 ├── utils/ # 工具函数 └── requirements.txt # 依赖列表对于长期运行的脚本建议使用系统服务方式部署Windows:使用pyinstaller打包为exepyinstaller --onefile --windowed main.py创建计划任务定期运行Linux:使用systemd创建服务单元文件配置为后台守护进程Mac:使用launchd创建plist文件设置为登录项自动启动实际使用中发现将脚本部署到树莓派等小型设备上是个不错的选择既不影响工作电脑性能又能24小时运行。