229 lines
4.9 KiB
Markdown
229 lines
4.9 KiB
Markdown
|
|
# 校园新闻爬虫服务
|
|||
|
|
|
|||
|
|
基于Python开发的新闻爬虫服务,用于自动抓取各大新闻网站的内容。
|
|||
|
|
|
|||
|
|
## 功能特性
|
|||
|
|
|
|||
|
|
- ✅ 支持多个新闻源(人民日报等)
|
|||
|
|
- ✅ 完整的类型校验(基于Pydantic)
|
|||
|
|
- ✅ 异步请求支持
|
|||
|
|
- ✅ 自动重试机制
|
|||
|
|
- ✅ 详细的日志记录
|
|||
|
|
- ✅ 代理支持
|
|||
|
|
- ✅ 数据验证和清洗
|
|||
|
|
- ✅ 多种输出格式(JSON/CSV)
|
|||
|
|
- ✅ 定时任务调度
|
|||
|
|
|
|||
|
|
## 项目结构
|
|||
|
|
|
|||
|
|
```
|
|||
|
|
schoolNewsCrawler/
|
|||
|
|
├── crawler/ # 爬虫模块
|
|||
|
|
│ ├── __init__.py
|
|||
|
|
│ ├── BaseCrawler.py # 基础爬虫类
|
|||
|
|
│ └── RmrbCrawler.py # 人民日报爬虫
|
|||
|
|
├── logs/ # 日志目录
|
|||
|
|
├── output/ # 输出目录
|
|||
|
|
├── main.py # 主程序入口
|
|||
|
|
├── config.py # 配置文件
|
|||
|
|
├── requirements.txt # 依赖包
|
|||
|
|
├── .env.example # 环境变量示例
|
|||
|
|
├── .gitignore # Git忽略文件
|
|||
|
|
└── README.md # 项目说明
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 安装依赖
|
|||
|
|
|
|||
|
|
### 1. 安装Python(需要Python 3.9+)
|
|||
|
|
|
|||
|
|
确保已安装Python 3.9或更高版本。
|
|||
|
|
|
|||
|
|
### 2. 创建虚拟环境(推荐)
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# Windows
|
|||
|
|
python -m venv venv
|
|||
|
|
venv\Scripts\activate
|
|||
|
|
|
|||
|
|
# Linux/Mac
|
|||
|
|
python3 -m venv venv
|
|||
|
|
source venv/bin/activate
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 3. 安装依赖包
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
pip install -r requirements.txt
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 配置
|
|||
|
|
|
|||
|
|
### 1. 复制环境变量文件
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
cp .env.example .env
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### 2. 修改配置
|
|||
|
|
|
|||
|
|
编辑 `.env` 文件,配置数据库连接、API地址等信息。
|
|||
|
|
|
|||
|
|
## 使用方法
|
|||
|
|
|
|||
|
|
### 命令行运行
|
|||
|
|
|
|||
|
|
```bash
|
|||
|
|
# 基本用法(默认爬取人民日报政治类新闻20条)
|
|||
|
|
python main.py
|
|||
|
|
|
|||
|
|
# 指定分类和数量
|
|||
|
|
python main.py politics 50
|
|||
|
|
|
|||
|
|
# 指定输出文件
|
|||
|
|
python main.py politics 50 output/news_politics.json
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
### Python代码调用
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from crawler.RmrbCrawler import RmrbCrawler
|
|||
|
|
|
|||
|
|
# 创建爬虫实例
|
|||
|
|
crawler = RmrbCrawler()
|
|||
|
|
|
|||
|
|
# 爬取新闻
|
|||
|
|
news_list = crawler.crawl(category="politics", limit=20)
|
|||
|
|
|
|||
|
|
# 处理新闻数据
|
|||
|
|
for news in news_list:
|
|||
|
|
print(f"标题: {news.title}")
|
|||
|
|
print(f"内容: {news.content[:100]}...")
|
|||
|
|
print(f"URL: {news.url}")
|
|||
|
|
print("-" * 60)
|
|||
|
|
|
|||
|
|
# 关闭爬虫
|
|||
|
|
crawler.close()
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 扩展新爬虫
|
|||
|
|
|
|||
|
|
创建新的爬虫类,继承 `BaseCrawler`:
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
from crawler.BaseCrawler import BaseCrawler, CrawlerConfig, NewsItem
|
|||
|
|
from typing import List, Optional
|
|||
|
|
|
|||
|
|
class MyNewsCrawler(BaseCrawler):
|
|||
|
|
"""自定义新闻爬虫"""
|
|||
|
|
|
|||
|
|
def __init__(self):
|
|||
|
|
config = CrawlerConfig(
|
|||
|
|
base_url="https://example.com",
|
|||
|
|
headers={
|
|||
|
|
'User-Agent': 'Mozilla/5.0 ...'
|
|||
|
|
}
|
|||
|
|
)
|
|||
|
|
super().__init__(config)
|
|||
|
|
|
|||
|
|
def crawl(self, limit: int = 20) -> List[NewsItem]:
|
|||
|
|
"""实现爬取逻辑"""
|
|||
|
|
# TODO: 实现具体的爬取逻辑
|
|||
|
|
pass
|
|||
|
|
|
|||
|
|
def parse_news_detail(self, url: str) -> Optional[NewsItem]:
|
|||
|
|
"""实现详情解析逻辑"""
|
|||
|
|
# TODO: 实现具体的解析逻辑
|
|||
|
|
pass
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 与Java定时任务集成
|
|||
|
|
|
|||
|
|
在Java的定时任务中调用Python爬虫:
|
|||
|
|
|
|||
|
|
```java
|
|||
|
|
@Component("newsCrawlerTask")
|
|||
|
|
public class NewsCrawlerTask {
|
|||
|
|
|
|||
|
|
public void execute() throws Exception {
|
|||
|
|
// 构建Python命令
|
|||
|
|
ProcessBuilder pb = new ProcessBuilder(
|
|||
|
|
"python",
|
|||
|
|
"main.py",
|
|||
|
|
"politics",
|
|||
|
|
"50"
|
|||
|
|
);
|
|||
|
|
|
|||
|
|
// 设置工作目录
|
|||
|
|
pb.directory(new File("../schoolNewsCrawler"));
|
|||
|
|
|
|||
|
|
// 执行命令
|
|||
|
|
Process process = pb.start();
|
|||
|
|
int exitCode = process.waitFor();
|
|||
|
|
|
|||
|
|
if (exitCode == 0) {
|
|||
|
|
log.info("新闻爬虫执行成功");
|
|||
|
|
} else {
|
|||
|
|
log.error("新闻爬虫执行失败");
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 数据模型
|
|||
|
|
|
|||
|
|
### NewsItem
|
|||
|
|
|
|||
|
|
```python
|
|||
|
|
{
|
|||
|
|
"title": "新闻标题",
|
|||
|
|
"content": "新闻内容",
|
|||
|
|
"url": "https://example.com/news/123",
|
|||
|
|
"publish_time": "2025-01-01 12:00:00",
|
|||
|
|
"author": "作者",
|
|||
|
|
"source": "人民日报",
|
|||
|
|
"category": "时政",
|
|||
|
|
"tags": ["标签1", "标签2"],
|
|||
|
|
"images": ["https://example.com/img1.jpg"]
|
|||
|
|
}
|
|||
|
|
```
|
|||
|
|
|
|||
|
|
## 日志
|
|||
|
|
|
|||
|
|
日志文件存储在 `logs/` 目录下,按日期自动分割:
|
|||
|
|
|
|||
|
|
- 文件命名:`crawler_YYYY-MM-DD.log`
|
|||
|
|
- 保留时间:30天(可配置)
|
|||
|
|
- 日志级别:DEBUG/INFO/WARNING/ERROR
|
|||
|
|
|
|||
|
|
## 注意事项
|
|||
|
|
|
|||
|
|
1. **遵守robots.txt**: 请尊重目标网站的爬虫协议
|
|||
|
|
2. **控制频率**: 避免频繁请求对目标网站造成压力
|
|||
|
|
3. **法律合规**: 仅用于学习和个人使用,不得用于商业用途
|
|||
|
|
4. **数据隐私**: 妥善保管爬取的数据,注意隐私保护
|
|||
|
|
|
|||
|
|
## 技术栈
|
|||
|
|
|
|||
|
|
- Python 3.9+
|
|||
|
|
- Requests - HTTP请求
|
|||
|
|
- BeautifulSoup4 - HTML解析
|
|||
|
|
- Pydantic - 数据验证
|
|||
|
|
- Loguru - 日志记录
|
|||
|
|
- Selenium - 浏览器自动化(可选)
|
|||
|
|
|
|||
|
|
## 开发工具
|
|||
|
|
|
|||
|
|
- MyPy - 静态类型检查
|
|||
|
|
- Black - 代码格式化
|
|||
|
|
- Flake8 - 代码风格检查
|
|||
|
|
- Pytest - 单元测试
|
|||
|
|
|
|||
|
|
## 作者
|
|||
|
|
|
|||
|
|
yslg @ xyzh
|
|||
|
|
|
|||
|
|
## 更新日期
|
|||
|
|
|
|||
|
|
2025-11-08
|
|||
|
|
|