diff --git a/schoolNewsCrawler/README.md b/schoolNewsCrawler/README.md new file mode 100644 index 0000000..25b51c3 --- /dev/null +++ b/schoolNewsCrawler/README.md @@ -0,0 +1,228 @@ +# 校园新闻爬虫服务 + +基于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 + diff --git a/schoolNewsCrawler/config.py b/schoolNewsCrawler/config.py new file mode 100644 index 0000000..33e9a5f --- /dev/null +++ b/schoolNewsCrawler/config.py @@ -0,0 +1,77 @@ +""" +爬虫配置文件 +""" + +import os +from typing import Dict +from pydantic_settings import BaseSettings +from pydantic import Field + + +class Settings(BaseSettings): + """应用配置""" + + # 爬虫配置 + REQUEST_TIMEOUT: int = Field(default=30, description="请求超时时间(秒)") + RETRY_TIMES: int = Field(default=3, description="重试次数") + CONCURRENT_REQUESTS: int = Field(default=5, description="并发请求数") + DOWNLOAD_DELAY: float = Field(default=1.0, description="下载延迟(秒)") + + # 代理配置 + USE_PROXY: bool = Field(default=False, description="是否使用代理") + PROXY_URL: str = Field(default="", description="代理地址") + + # 数据库配置(用于存储爬取的数据) + DB_HOST: str = Field(default="localhost", description="数据库主机") + DB_PORT: int = Field(default=3306, description="数据库端口") + DB_USER: str = Field(default="root", description="数据库用户名") + DB_PASSWORD: str = Field(default="", description="数据库密码") + DB_NAME: str = Field(default="school_news", description="数据库名称") + + # 日志配置 + LOG_LEVEL: str = Field(default="INFO", description="日志级别") + LOG_DIR: str = Field(default="logs", description="日志目录") + LOG_RETENTION: str = Field(default="30 days", description="日志保留时间") + + # 输出配置 + OUTPUT_DIR: str = Field(default="output", description="输出目录") + OUTPUT_FORMAT: str = Field(default="json", description="输出格式(json/csv)") + + # 人民日报配置 + RMRB_BASE_URL: str = Field(default="http://www.people.com.cn", description="人民日报基础URL") + RMRB_CATEGORIES: Dict[str, str] = Field( + default_factory=lambda: { + "politics": "时政", + "society": "社会", + "world": "国际", + "finance": "财经", + "tech": "科技", + "culture": "文化", + "education": "教育" + }, + description="人民日报新闻分类" + ) + + # API配置(用于将爬取的数据推送到后端) + API_BASE_URL: str = Field(default="http://localhost:8080", description="后端API地址") + API_TOKEN: str = Field(default="", description="API认证Token") + + class Config: + env_file = ".env" + env_file_encoding = "utf-8" + case_sensitive = True + + +# 创建全局配置实例 +settings = Settings() + + +# 常用User-Agent列表 +USER_AGENTS = [ + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/119.0.0.0 Safari/537.36', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36', + 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:121.0) Gecko/20100101 Firefox/121.0', + 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.1 Safari/605.1.15', +] + diff --git a/schoolNewsCrawler/core/ResultDomain.py b/schoolNewsCrawler/core/ResultDomain.py new file mode 100644 index 0000000..7ce9c1b --- /dev/null +++ b/schoolNewsCrawler/core/ResultDomain.py @@ -0,0 +1,9 @@ +from pydantic import BaseModel, Field, HttpUrl +from typing import Any, List, Optional + +class ResultDomain(BaseModel): + code: int = Field(..., description="状态码") + message: str = Field(..., description="消息") + success: bool = Field(..., description="是否成功") + data: Optional[Any] = Field(default=None, description="数据") + dataList: Optional[List[Any]] = Field(default=None, description="数据列表") diff --git a/schoolNewsCrawler/crawl4AI/PeopleNetCrewer.py b/schoolNewsCrawler/crawl4AI/PeopleNetCrewer.py new file mode 100644 index 0000000..fcf3495 --- /dev/null +++ b/schoolNewsCrawler/crawl4AI/PeopleNetCrewer.py @@ -0,0 +1,317 @@ +""" +使用 Crawl4AI 爬取人民网新闻 +""" +from typing import List, Optional +from loguru import logger +import re +from datetime import datetime +from crawler.BaseCrawler import NewsItem +import asyncio + + +class PeopleNetCrewer: + """使用 Crawl4AI 爬取人民网新闻""" + + def __init__(self, chrome_path: Optional[str] = None): + """ + 初始化人民网爬虫 + + Args: + chrome_path: Chrome 浏览器可执行文件路径,如果为 None 则使用系统默认路径 + """ + self.base_url = "http://www.people.com.cn" + self.chrome_path = chrome_path + self.crawler = None + logger.info(f"初始化人民网爬虫 (Crawl4AI)") + + async def _get_crawler(self): + """获取或创建爬虫实例""" + if self.crawler is None: + try: + from crawl4ai import AsyncWebCrawler + except ImportError: + logger.error("请先安装 crawl4ai: pip install crawl4ai") + raise ImportError("crawl4ai 未安装") + + # 配置浏览器选项,使用本地 Chrome + browser_config = { + "headless": True, + "verbose": False, + } + + # 如果指定了 Chrome 路径,使用指定路径 + if self.chrome_path: + browser_config["executable_path"] = self.chrome_path + logger.info(f"使用指定的 Chrome 路径: {self.chrome_path}") + else: + # 使用本地安装的 Chrome(通过 channel 参数) + browser_config["channel"] = "chrome" + logger.info("使用本地安装的 Chrome 浏览器") + + try: + self.crawler = AsyncWebCrawler( + browser_type="chromium", + browser_config=browser_config + ) + except Exception as e: + logger.error(f"创建爬虫实例失败: {str(e)}") + # 如果使用 channel 失败,尝试使用 executable_path + if not self.chrome_path and "channel" in browser_config: + logger.warning("使用 channel 参数失败,尝试其他方式...") + # 尝试常见的 Chrome 路径 + import os + common_paths = [ + r"C:\Program Files\Google\Chrome\Application\chrome.exe", + r"C:\Program Files (x86)\Google\Chrome\Application\chrome.exe", + os.path.expanduser(r"~\AppData\Local\Google\Chrome\Application\chrome.exe"), + ] + for path in common_paths: + if os.path.exists(path): + browser_config.pop("channel", None) + browser_config["executable_path"] = path + logger.info(f"找到 Chrome 路径: {path}") + try: + self.crawler = AsyncWebCrawler( + browser_type="chromium", + browser_config=browser_config + ) + break + except Exception: + continue + else: + raise + else: + raise + return self.crawler + + async def crawl(self, category: str = "politics", limit: int = 20) -> List[NewsItem]: + """ + 爬取人民网新闻列表 + + Args: + category: 新闻分类(politics-政治, society-社会, world-国际等) + limit: 爬取数量限制 + + Returns: + 新闻列表 + """ + news_list = [] + + try: + crawler = await self._get_crawler() + + # 构建列表页URL + list_url = f"{self.base_url}/{category}/index.html" + logger.info(f"开始爬取人民网新闻: {list_url}") + + # 使用 Crawl4AI 爬取页面 + result = await crawler.arun(url=list_url) + + if not result.success: + logger.error(f"爬取失败: {list_url}") + return news_list + + html_content = result.html + if not html_content: + logger.warning("未获取到页面内容") + return news_list + + # 解析新闻列表 + from bs4 import BeautifulSoup + soup = BeautifulSoup(html_content, 'lxml') + + # 根据人民网实际结构调整选择器 + # 这里使用通用的新闻列表选择器,实际使用时需要根据网站结构调整 + news_items = soup.select('.news-list .news-item, .list-item, .news-item, article') + + if not news_items: + # 尝试其他可能的选择器 + news_items = soup.select('a[href*="/n1/"], a[href*="/n2/"], a[href*="/n3/"]') + + logger.info(f"找到 {len(news_items)} 个新闻链接") + + # 提取新闻链接并爬取详情 + processed_urls = set() + for item in news_items[:limit * 2]: # 多取一些,因为有些链接可能无效 + try: + # 提取链接 + if item.name == 'a': + link_tag = item + else: + link_tag = item.select_one('a') + + if not link_tag: + continue + + news_url = link_tag.get('href', '') + if not news_url: + continue + + # 处理相对路径 + if not news_url.startswith('http'): + if news_url.startswith('/'): + news_url = self.base_url + news_url + else: + news_url = f"{self.base_url}/{news_url}" + + # 跳过重复链接 + if news_url in processed_urls: + continue + processed_urls.add(news_url) + + # 解析新闻详情 + news = await self.parse_news_detail(news_url) + if news: + news_list.append(news) + logger.info(f"成功爬取新闻: {news.title}") + + if len(news_list) >= limit: + break + + except Exception as e: + logger.error(f"处理新闻项失败: {str(e)}") + continue + + logger.info(f"爬取完成,共获取 {len(news_list)} 条新闻") + + except Exception as e: + logger.error(f"爬取新闻列表失败: {str(e)}") + + return news_list + + async def parse_news_detail(self, url: str) -> Optional[NewsItem]: + """ + 解析人民网新闻详情 + + Args: + url: 新闻详情页URL + + Returns: + 新闻对象 + """ + try: + crawler = await self._get_crawler() + + # 使用 Crawl4AI 爬取详情页 + result = await crawler.arun(url=url) + + if not result.success: + logger.warning(f"爬取详情页失败: {url}") + return None + + html_content = result.html + if not html_content: + return None + + from bs4 import BeautifulSoup + soup = BeautifulSoup(html_content, 'lxml') + + # 提取标题 + title_tag = soup.select_one('h1, .title, .article-title, .p_title') + title = title_tag.get_text(strip=True) if title_tag else "未知标题" + + if title == "未知标题" or not title: + logger.warning(f"无法提取标题: {url}") + return None + + # 提取内容 + content_tag = soup.select_one( + '.article-content, .content, .text-content, .p_content, ' + '.article-body, .article-text, #articleContent' + ) + content = "" + if content_tag: + # 移除脚本和样式标签 + for script in content_tag(['script', 'style', 'noscript']): + script.decompose() + content = content_tag.get_text(separator='\n', strip=True) + + # 提取发布时间 + time_tag = soup.select_one( + '.time, .publish-time, .date, .p_time, .article-time, ' + 'time[datetime], .pubtime' + ) + publish_time = None + if time_tag: + time_text = time_tag.get_text(strip=True) + if not time_text: + time_text = time_tag.get('datetime', '') + publish_time = self._parse_time(time_text) + + # 提取作者 + author_tag = soup.select_one('.author, .writer, .p_author, .article-author') + author = None + if author_tag: + author = author_tag.get_text(strip=True) + + # 提取图片 + images = [] + img_tags = soup.select('.article-content img, .content img, .p_content img') + for img in img_tags: + img_url = img.get('src', '') or img.get('data-src', '') + if img_url and not img_url.startswith('data:'): + if not img_url.startswith('http'): + if img_url.startswith('/'): + img_url = self.base_url + img_url + else: + img_url = f"{self.base_url}/{img_url}" + images.append(img_url) + + # 创建新闻对象 + news = NewsItem( + title=title, + content=content, + url=url, + publish_time=publish_time, + author=author, + source="人民网", + category="时政", + images=images + ) + + return news + + except Exception as e: + logger.error(f"解析新闻详情失败 [{url}]: {str(e)}") + return None + + def _parse_time(self, time_text: str) -> Optional[str]: + """ + 解析时间字符串 + + Args: + time_text: 时间文本 + + Returns: + 标准化的时间字符串 + """ + if not time_text: + return None + + try: + # 尝试匹配常见的时间格式 + patterns = [ + r'(\d{4})-(\d{2})-(\d{2})\s+(\d{2}):(\d{2}):(\d{2})', + r'(\d{4})年(\d{2})月(\d{2})日\s+(\d{2}):(\d{2})', + r'(\d{4})/(\d{2})/(\d{2})\s+(\d{2}):(\d{2})', + r'(\d{4})-(\d{2})-(\d{2})', + ] + + for pattern in patterns: + match = re.search(pattern, time_text) + if match: + return time_text.strip() + + return time_text.strip() + + except Exception as e: + logger.warning(f"时间解析失败: {str(e)}") + return None + + async def close(self): + """关闭爬虫,释放资源""" + if self.crawler: + await self.crawler.close() + self.crawler = None + logger.info("爬虫已关闭") + diff --git a/schoolNewsCrawler/crawl4AI/README.md b/schoolNewsCrawler/crawl4AI/README.md new file mode 100644 index 0000000..cc995cf --- /dev/null +++ b/schoolNewsCrawler/crawl4AI/README.md @@ -0,0 +1,77 @@ +# Crawl4AI 人民网新闻爬虫 + +使用 Crawl4AI 框架爬取人民网新闻,支持使用本地 Chrome 浏览器。 + +## 安装依赖 + +```bash +pip install crawl4ai playwright +playwright install chromium # 或者使用本地 Chrome +``` + +## 使用方法 + +### 基本使用 + +```bash +# 使用默认配置(自动使用本地 Chrome) +python crawl4ai/main.py [category] [limit] [output_file] + +# 示例 +python crawl4ai/main.py politics 20 output/news.json +``` + +### 指定 Chrome 路径 + +```bash +# 指定 Chrome 可执行文件路径 +python crawl4ai/main.py politics 20 output/news.json "C:\Program Files\Google\Chrome\Application\chrome.exe" +``` + +### 在代码中使用 + +```python +import asyncio +from crawl4ai.PeopleNetCrewer import PeopleNetCrewer + +async def main(): + # 使用默认 Chrome(自动检测) + crewer = PeopleNetCrewer() + + # 或者指定 Chrome 路径 + # crewer = PeopleNetCrewer(chrome_path="C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe") + + news_list = await crewer.crawl(category="politics", limit=20) + + for news in news_list: + print(f"标题: {news.title}") + print(f"链接: {news.url}") + print("-" * 50) + + await crewer.close() + +if __name__ == "__main__": + asyncio.run(main()) +``` + +## 配置说明 + +### 使用本地 Chrome + +代码会自动尝试使用本地安装的 Chrome 浏览器。如果未指定 `chrome_path`,会通过 `channel="chrome"` 参数使用系统默认的 Chrome。 + +### 浏览器配置 + +在 `PeopleNetCrewer` 类中,可以通过修改 `_get_crawler` 方法中的 `browser_config` 来调整浏览器行为: + +- `headless`: 是否无头模式(默认 True) +- `verbose`: 是否显示详细日志(默认 False) +- `channel`: 浏览器通道("chrome" 表示使用本地 Chrome) +- `executable_path`: 指定浏览器可执行文件路径 + +## 注意事项 + +1. 确保已安装 Chrome 浏览器 +2. 如果遇到 Playwright 浏览器未找到的错误,可以运行 `playwright install chromium` 安装 Playwright 自带的浏览器 +3. 使用本地 Chrome 时,确保 Chrome 版本与 Playwright 兼容 + diff --git a/schoolNewsCrawler/crawl4AI/__init__.py b/schoolNewsCrawler/crawl4AI/__init__.py new file mode 100644 index 0000000..7f38209 --- /dev/null +++ b/schoolNewsCrawler/crawl4AI/__init__.py @@ -0,0 +1,9 @@ +""" +Crawl4AI 爬虫模块 +使用 Crawl4AI 进行动态网页爬取 +""" + +from .PeopleNetCrewer import PeopleNetCrewer + +__all__ = ['PeopleNetCrewer'] + diff --git a/schoolNewsCrawler/crawl4AI/main.py b/schoolNewsCrawler/crawl4AI/main.py new file mode 100644 index 0000000..887d35e --- /dev/null +++ b/schoolNewsCrawler/crawl4AI/main.py @@ -0,0 +1,147 @@ +""" +使用 Crawl4AI 爬取人民网新闻的主程序 +""" +import sys +import json +import asyncio +from typing import List +from loguru import logger +from crawl4ai.PeopleNetCrewer import PeopleNetCrewer + + +# 配置日志 +logger.remove() # 移除默认处理器 +logger.add( + sys.stdout, + format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}", + level="INFO" +) +logger.add( + "logs/crewer_{time:YYYY-MM-DD}.log", + rotation="00:00", + retention="30 days", + encoding="utf-8", + level="DEBUG" +) + + +async def crawl_people_net_news( + category: str = "politics", + limit: int = 20, + chrome_path: str = None +) -> List[dict]: + """ + 使用 Crawl4AI 爬取人民网新闻 + + Args: + category: 新闻分类 + limit: 爬取数量 + chrome_path: Chrome 浏览器可执行文件路径(可选) + + Returns: + 新闻列表(字典格式) + """ + logger.info(f"开始爬取人民网新闻 - 分类: {category}, 数量: {limit}") + + crewer = None + try: + crewer = PeopleNetCrewer(chrome_path=chrome_path) + news_list = await crewer.crawl(category=category, limit=limit) + + # 转换为字典列表 + result = [news.model_dump() for news in news_list] + + logger.info(f"爬取完成,共获取 {len(result)} 条新闻") + return result + + except Exception as e: + logger.error(f"爬取失败: {str(e)}") + import traceback + logger.error(traceback.format_exc()) + return [] + + finally: + if crewer: + await crewer.close() + + +def save_to_json(news_list: List[dict], output_file: str = "output/news.json"): + """ + 保存新闻到JSON文件 + + Args: + news_list: 新闻列表 + output_file: 输出文件路径 + """ + try: + import os + os.makedirs(os.path.dirname(output_file), exist_ok=True) + + with open(output_file, 'w', encoding='utf-8') as f: + json.dump(news_list, f, ensure_ascii=False, indent=2) + + logger.info(f"新闻已保存到: {output_file}") + + except Exception as e: + logger.error(f"保存文件失败: {str(e)}") + + +async def main_async(): + """异步主函数""" + # 解析命令行参数 + category = "politics" + limit = 20 + output_file = "output/news.json" + chrome_path = None + + if len(sys.argv) > 1: + category = sys.argv[1] + if len(sys.argv) > 2: + limit = int(sys.argv[2]) + if len(sys.argv) > 3: + output_file = sys.argv[3] + if len(sys.argv) > 4: + chrome_path = sys.argv[4] + + logger.info("=" * 60) + logger.info("人民网新闻爬虫程序启动 (Crawl4AI)") + logger.info("=" * 60) + + # 爬取新闻 + news_list = await crawl_people_net_news( + category=category, + limit=limit, + chrome_path=chrome_path + ) + + # 保存结果 + if news_list: + save_to_json(news_list, output_file) + + # 输出统计信息 + logger.info(f"爬取统计:") + logger.info(f" - 成功: {len(news_list)} 条") + logger.info(f" - 失败: {limit - len(news_list)} 条") + else: + logger.warning("未获取到任何新闻") + + logger.info("=" * 60) + logger.info("人民网新闻爬虫程序结束") + logger.info("=" * 60) + + +def main(): + """主函数入口""" + try: + asyncio.run(main_async()) + except KeyboardInterrupt: + logger.info("程序被用户中断") + except Exception as e: + logger.error(f"程序运行出错: {str(e)}") + import traceback + logger.error(traceback.format_exc()) + + +if __name__ == "__main__": + main() + diff --git a/schoolNewsCrawler/crawler/BaseCrawler.py b/schoolNewsCrawler/crawler/BaseCrawler.py new file mode 100644 index 0000000..427d6af --- /dev/null +++ b/schoolNewsCrawler/crawler/BaseCrawler.py @@ -0,0 +1,152 @@ +# 定义基础爬虫类 +from typing import Dict, Optional, List, Any +from abc import ABC, abstractmethod +import requests +from bs4 import BeautifulSoup +from loguru import logger +from pydantic import BaseModel, Field, HttpUrl + + +class UrlConfig(BaseModel): + """URL配置数据模型""" + url: str = Field(..., description="请求URL") + params: Optional[Dict[str, Any]] = Field(default=None, description="请求参数") + method: str = Field(default="GET", description="请求方法") + + class Config: + # 允许任意类型 + arbitrary_types_allowed = True + + +class CrawlerConfig(BaseModel): + """爬虫配置数据模型""" + base_url: str = Field(..., description="基础URL") + urls: Dict[str, UrlConfig] = Field( + default_factory=dict, + description="URL配置映射,如 {'search': UrlConfig(...), 'list': UrlConfig(...)}" + ) + headers: Dict[str, str] = Field( + default_factory=lambda: { + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36' + }, + description="HTTP请求头" + ) + timeout: int = Field(default=30, description="请求超时时间(秒)") + retry_times: int = Field(default=3, description="重试次数") + proxy: Optional[str] = Field(default=None, description="代理地址") + + class Config: + # 允许任意类型 + arbitrary_types_allowed = True + + +class NewsItem(BaseModel): + """新闻数据模型""" + title: str = Field(..., description="新闻标题") + contentRows: List[Dict[str, Any]] = Field(..., description="新闻内容") + url: str = Field(..., description="新闻链接") + publishTime: Optional[str] = Field(default=None, description="发布时间") + author: Optional[str] = Field(default=None, description="作者") + source: Optional[str] = Field(default=None, description="来源") + category: Optional[str] = Field(default=None, description="分类") + + +class BaseCrawler(ABC): + """基础爬虫类""" + + def __init__(self, config: CrawlerConfig): + """ + 初始化爬虫 + + Args: + config: 爬虫配置对象 + """ + self.config = config + self.session = requests.Session() + self.session.headers.update(config.headers) + logger.info(f"初始化爬虫: {self.__class__.__name__}") + + def fetch(self, url: str, method: str = "GET", data: Optional[Dict[str, Any]] = None, **kwargs) -> Optional[requests.Response]: + """ + 发送HTTP请求 + + Args: + url: 请求URL + method: 请求方法 + data: 请求数据 + **kwargs: 其他请求参数 + + Returns: + 响应对象,失败返回None + """ + for attempt in range(self.config.retry_times): + try: + logger.info(f"请求URL: {url} (尝试 {attempt + 1}/{self.config.retry_times})") + + response = self.session.request( + method=method, + url=url, + headers=self.config.headers, + data=data, + timeout=self.config.timeout, + proxies={'http': self.config.proxy, 'https': self.config.proxy} if self.config.proxy else None, + **kwargs + ) + response.raise_for_status() + return response + + except requests.RequestException as e: + logger.warning(f"请求失败 (尝试 {attempt + 1}/{self.config.retry_times}): {str(e)}") + if attempt == self.config.retry_times - 1: + logger.error(f"请求最终失败: {url}") + return None + + return None + + def parse_html(self, html, parser: str = "lxml") -> Optional[BeautifulSoup]: + """ + 解析HTML + + Args: + html: HTML字符串或字节数据(bytes),BeautifulSoup会自动检测编码 + parser: 解析器类型 + + Returns: + BeautifulSoup对象 + """ + try: + # BeautifulSoup 可以自动处理编码: + # - 如果传入 bytes,会从 HTML 的 标签或响应头自动检测编码 + # - 如果传入 str,会直接使用 + return BeautifulSoup(html, parser) + except Exception as e: + logger.error(f"HTML解析失败: {str(e)}") + return None + + @abstractmethod + def crawl(self) -> List[NewsItem]: + """ + 爬取新闻(子类必须实现) + + Returns: + 新闻列表 + """ + pass + + @abstractmethod + def parse_news_detail(self, url: str) -> Optional[NewsItem]: + """ + 解析新闻详情(子类必须实现) + + Args: + url: 新闻详情页URL + + Returns: + 新闻对象 + """ + pass + + def close(self): + """关闭会话""" + self.session.close() + logger.info(f"关闭爬虫: {self.__class__.__name__}") \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/RmrbCrawler.py b/schoolNewsCrawler/crawler/RmrbCrawler.py new file mode 100644 index 0000000..03475c7 --- /dev/null +++ b/schoolNewsCrawler/crawler/RmrbCrawler.py @@ -0,0 +1,415 @@ +# 人民日报爬虫 +from typing import List, Optional +from core import ResultDomain +from crawler.BaseCrawler import BaseCrawler, CrawlerConfig, NewsItem, UrlConfig +from loguru import logger +import re +import chardet +from datetime import datetime + + +class RmrbCrawler(BaseCrawler): + """人民日报新闻爬虫""" + + def __init__(self): + """初始化人民日报爬虫""" + config = CrawlerConfig( + base_url="http://www.people.com.cn", + urls={ + "search": UrlConfig( + url="http://search.people.cn/search-platform/front/search", + method="POST", + params={ + "key": "", + "page": 1, + "limit": 10, + "hasTitle": True, + "hasContent": True, + "isFuzzy": True, + "type": 0, # 0 所有,1 新闻,2 互动,3 报刊,4 图片,5 视频 + "sortType": 2, # 1 按相关度,2 按时间 + "startTime": 0, + "endTime": 0 + }, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Content-Type': 'application/json;charset=UTF-8' + } + ), + "hot_point_rank": UrlConfig( + url="http://search.people.cn/search-platform/front/searchRank", + method="GET", + params={}, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Content-Type': 'application/json;charset=UTF-8' + } + ), + "one_day_trending_news": UrlConfig( + url=lambda date: f"http://www.people.com.cn/GB/59476/review/{date}.html", # date:YYYYMMdd + method="GET", + params={}, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36', + 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7', + 'Accept-Language': 'zh-CN,zh;q=0.9', + } + ) + }, + ) + super().__init__(config) + + def search(self, key: str, total: int = 10, news_type: int = 0) -> ResultDomain: + """ + 搜索人民日报新闻 + + Args: + key: 搜索关键词 + total: 总数量 + news_type: 新闻类型 (0=全部, 1=新闻, 2=互动, 3=报刊, 4=图片, 5=视频) + + Returns: + 新闻列表 + """ + try: + resultDomain = ResultDomain() + news_list = [] + resultDomain.dataList = news_list + # 获取搜索配置 + search_config = self.config.urls.get("search") + if not search_config: + logger.error("未找到搜索URL配置") + resultDomain.code = 0 + resultDomain.message = "未找到搜索URL配置" + resultDomain.success = False + return resultDomain + + page = 1 + limit = 10 + # 准备搜索参数 + search_data = search_config.params.copy() + search_data["key"] = key + search_data["limit"] = limit + search_data["type"] = news_type + + while len(news_list) < total: + search_data["page"] = page + response = self.fetch(search_config.url, method=search_config.method, data=search_data, headers=search_config.headers) + response_json = response.json() + if response_json.get("code") == 0: + records = response_json.get("data", {}).get("records", []) + for record in records: + news = self.parse_news_detail(record.get("url")) + news_list.append(news) + else: + resultDomain.code = response_json.get("code") + resultDomain.message = "获取搜索结果失败" + response_json.get("message") + resultDomain.success = False + return resultDomain + page += 1 + + resultDomain.success = True + resultDomain.code = 0 + logger.info(f"搜索到 {len(news_list)} 条新闻") + return resultDomain + + except Exception as e: + logger.error(f"搜索人民日报新闻失败: {str(e)}") + resultDomain.code = 0 + resultDomain.message = "搜索人民日报新闻失败" + str(e) + resultDomain.success = False + return resultDomain + + def hotPointRank(self) -> ResultDomain: + """ + 获取人民日报热点排行 + """ + try: + hot_point_rank_config = self.config.urls.get("hot_point_rank") + resultDomain = ResultDomain() + news_list = [] + resultDomain.dataList = news_list + + if not hot_point_rank_config: + logger.error("未找到热点排行URL配置") + resultDomain.code = 0 + resultDomain.message = "未找到热点排行URL配置" + resultDomain.success = False + return resultDomain + response = self.fetch(hot_point_rank_config.url, method=hot_point_rank_config.method, headers=hot_point_rank_config.headers) + response_json = response.json() + + if response_json.get("code") == 0: + records = response_json.get("data", []) + for record in records: + news = self.parse_news_detail(record.get("url")) + news_list.append(news) + else: + resultDomain.code = response_json.get("code") + resultDomain.message = "获取人民日报热点排行失败" + response_json.get("message") + resultDomain.success = False + return resultDomain + resultDomain.success = True + resultDomain.code = 0 + logger.info(f"获取人民日报热点排行成功") + return resultDomain + except Exception as e: + logger.error(f"获取人民日报热点排行失败: {str(e)}") + resultDomain.code = 0 + resultDomain.message = "获取人民日报热点排行失败" + str(e) + resultDomain.success = False + return resultDomain + + def getOneDayTrendingNews(self, date: datetime) -> ResultDomain: + """ + 获取人民日报一天内的热点新闻 + """ + try: + resultDomain = ResultDomain() + news_list = [] + resultDomain.dataList = news_list + resultDomain.success = True + resultDomain.code = 0 + logger.info(f"获取人民日报一天内的热点新闻成功") + date_str = date.strftime("%Y%m%d") + one_day_trending_news_config = self.config.urls.get("one_day_trending_news") + one_day_trending_news_config.url = one_day_trending_news_config.url(date_str) + response = self.fetch(one_day_trending_news_config.url, method=one_day_trending_news_config.method, headers=one_day_trending_news_config.headers) + if not response: + logger.error(f"获取响应失败: {one_day_trending_news_config.url}") + resultDomain.code = 0 + resultDomain.message = "获取响应失败" + one_day_trending_news_config.url + resultDomain.success = False + return resultDomain + soup = self.parse_html(response.content) + if not soup: + logger.error(f"解析HTML失败: {one_day_trending_news_config.url}") + resultDomain.code = 0 + resultDomain.message = "解析HTML失败" + one_day_trending_news_config.url + resultDomain.success = False + return resultDomain + + all_doc_urls = [] + all_doc_urls.extend(a_tags) + + bg01 = soup.find('td', class_="bg01") + indexfont13 = bg01.find('td', class_='indexfont13') + # 获取该 td 下的所有 a 标签 + a_tags = indexfont13.find_all('a') + + bg02 = soup.find('td', class_="bg02") + p6 = bg02.find('td', class_='p6') + a_tags_p6 = p6.find_all('a') + all_doc_urls.extend(a_tags_p6) + + for a_tag in all_doc_urls: + news = self.parse_news_detail(a_tag.get('href')) + news_list.append(news) + + return resultDomain + except Exception as e: + logger.error(f"获取人民日报一天内的热点新闻失败: {str(e)}") + resultDomain.code = 0 + resultDomain.message = "获取人民日报一天内的热点新闻失败" + str(e) + resultDomain.success = False + return resultDomain + + def getDaysTrendingNews(self, start_date: datetime, end_date: datetime) -> ResultDomain: + """ + 获取人民日报多天内的热点新闻 + """ + try: + resultDomain = ResultDomain() + news_list = [] + resultDomain.dataList = news_list + resultDomain.success = True + resultDomain.code = 0 + resultDomain.message = "获取人民日报多天内的热点新闻成功" + for date in range(start_date, end_date): + resultDomain = self.getOneDayTrendingNews(date) + if not resultDomain.success: + continue + news_list.extend(resultDomain.dataList) + + logger.info(f"获取人民日报多天内的热点新闻成功") + return resultDomain + except Exception as e: + logger.error(f"获取人民日报多天内的热点新闻失败: {str(e)}") + resultDomain.code = 0 + resultDomain.message = "获取人民日报多天内的热点新闻失败" + str(e) + resultDomain.success = False + return resultDomain + + def parse_news_detail(self, url: str) -> Optional[NewsItem]: + """ + 解析人民日报新闻详情 + + Args: + url: 新闻详情页URL + + Returns: + 新闻对象 + """ + try: + response = self.fetch(url) + + if not response: + logger.error(f"获取响应失败: {url}") + return None + + # BeautifulSoup 可以自动检测并解码编码,直接传入字节数据即可 + # 它会从 HTML 的 标签或响应头自动检测编码 + soup = self.parse_html(response.content) + if not soup: + logger.error("解析HTML失败") + return None + + # 提取主内容区域 + main_div = soup.find("div", class_="layout rm_txt cf") + if not main_div: + logger.error("未找到主内容区域") + return None + + # 提取文章区域 + article_div = main_div.find("div", class_="col col-1") + if not article_div: + logger.error("未找到文章区域") + return None + + # 提取标题 + title_tag = article_div.select_one("h1") + title = title_tag.get_text(strip=True) if title_tag else "" + + # 提取作者 + author_tag = article_div.select_one("div.author.cf") + author = author_tag.get_text(strip=True) if author_tag else "" + + # 提取发布时间和来源 + channel_div = article_div.select_one("div.channel.cf") + publish_time = "" + source = "" + + if channel_div: + channel_info = channel_div.select_one("div.col-1-1") + if channel_info: + channel_text = channel_info.get_text(strip=True) + # 解析时间格式:2025年11月10日05:51 | 来源:人民网-人民日报 + if '|' in channel_text: + parts = channel_text.split('|') + publish_time = parts[0].strip() if parts else "" + # 从 标签中提取来源 + source_tag = channel_info.select_one("a") + if source_tag: + source = source_tag.get_text(strip=True) + elif len(parts) > 1 and '来源' in parts[1]: + # 如果没有 标签,从文本中提取 + source = parts[1].replace('来源:', '').strip() + + # 提取内容 + content_div = article_div.select_one('div.rm_txt_con.cf') + contents = [] # 构建一个富文本内容 + pList = content_div.find_all("p") # 所有p标签 + # 解析p标签 变为quill富文本 + for p in pList: + # 获取p的class内容 + p_style = p.get("style") + content = "" + tag = "p" + if p.find('img'): + tag = "img" + src = p.find('img').get('src') + if not src.startswith("http") and src: + src = self.config.base_url + src + content = f"" + + elif p.find('video'): + tag = "video" + src = p.find('video').get('src') + if not src.startswith("http") and src: + src = self.config.base_url + src + content = f"
+ +
+ +
+ +
+
+ 人民网 +
+
+
+ +
+ +
+ + +
+ +
+ +
+ 人民网>>国际 +
+ +
+
+

+

西班牙国王费利佩六世今起对我国进行国事访问

+

+
+
+
+ 2025年11月10日05:51 | 来源:人民网-人民日报222 +
+
+ 小字号 +
+
+ +
+
+
+

点击播报本文,约

+
+
+
+

+ + +

+
+
+
+
+

+
+

  费利佩六世国王

  应国家主席习近平邀请,西班牙国王费利佩六世将于11月10日至13日对中国进行国事访问。

+

  费利佩六世,1968年1月生于西班牙马德里,法学学士、国际关系学硕士。1986年1月被立为王储。2014年6月继承王位。同莱蒂西娅王后育有王储莱昂诺尔和索菲娅两位公主。

+

  (新华社北京11月9日电)

+

  《 人民日报 》( 2025年11月10日 03 版)

+
+
(责编:袁勃、赵欣悦)
+ +

分享让更多人看到

+
+ + + +
+ +
+ + +
+ +
+ +
+ +
+ + + + +
+
+ +
+ +
+
+
推荐阅读
+
+
+
+
    +
+
+ +
+
+ +
+
+ +
+
+
+ + + +
返回顶部
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/response2.html b/schoolNewsCrawler/crawler/response2.html new file mode 100644 index 0000000..3035856 --- /dev/null +++ b/schoolNewsCrawler/crawler/response2.html @@ -0,0 +1,583 @@ + + + + + + +习言道|建好这个“港”,习近平有深远考量--时政--人民网 + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ +
+ +
+ +
+
+ 人民网 +
+
+
+ +
+ +
+ + + +
+ 人民网>>要闻播报 +
+ +
+
+

+

习言道|建好这个“港”,习近平有深远考量

+

+
+
+
+ 2025年11月10日09:26 | 来源:中国新闻网222 +
+
+ 小字号 +
+
+ +
+
+
+

点击播报本文,约

+
+
+
+

+ + +

+
+
+
+
+

+
+

+

中新网11月8日电 题:建好这个“港”,习近平有深远考量

+

党的二十届四中全会后首次到地方,习近平总书记来到了海南三亚。

+

再有一个多月,12月18日,海南自由贸易港将正式启动全岛封关。11月6日,在听取海南自由贸易港建设工作汇报时,习近平总书记强调,各级各有关方面要精心准备,确保平稳有序。

+

对于自由贸易港建设,总书记一直寄予厚望。

+

20世纪80年代,在厦门工作期间,习近平同志就曾牵头研究自由贸易港问题并将部分政策付诸实施。彼时,中国开放的大门刚刚打开。

+

多年后,这一任务交到了海南手中。

+

为什么是海南?从客观条件看,海南是我国最大的经济特区,地理位置独特,拥有全国最好的生态环境,同时又是相对独立的地理单元,具有成为全国改革开放试验田的独特优势。

+

从历史看,海南之所以能从一个边陲海岛发展成为我国改革开放的重要窗口,正是得益于深化改革、扩大开放。建设自贸港,是海南开放发展道路的延续,也是面向未来发展的需要。

+

从现实看,作为引领我国新时代对外开放的鲜明旗帜,海南自贸港建设不仅事关海南自身发展,更关乎中国改革开放全局。

+

“由海南来完成这项历史性任务,这也是中国特色社会主义经济特区建设的一个战略安排,不断摸索、大胆试验,现在蹚出来一条路子。”2022年在海南考察时,对于海南自贸港建设的未来,习近平总书记曾饱含期待。

+

只有敢于走别人没有走过的路,才能收获别样的风景。

+

从2018年党中央决定支持海南全岛建设自由贸易试验区,到2020年《海南自由贸易港建设总体方案》发布,再到海南自贸港连续7年被写入政府工作报告……一系列顶层设计推动海南自贸港建设取得重要阶段性成效,为启动全岛封关运作打下坚实基础。

+

美丽海岛持续释放活力,海南外贸连续5年增长,累计176个国家和地区在此投资。

+

这次在海南,习近平总书记再次强调海南自贸港的定位——

+

“高标准建设海南自由贸易港,主要目的是促进海南高质量发展,助力全国构建新发展格局。”

+

“建设海南自由贸易港的战略目标,就是要把海南自由贸易港打造成为引领我国新时代对外开放的重要门户。”

+

从海南到全国,从中国到世界,总书记点明中国特色自由贸易港的重要使命与历史方位。

+

此次,在海南自贸港将迈入全岛封关运作新阶段之际,总书记再次作出新部署。

+

“进一步提高贸易投资自由化便利化水平”“着力打造市场化法治化国际化一流营商环境”“越是扩大开放,越要统筹发展和安全”……有方向指引,有具体要求,也有深远考量。

+

前不久,党的二十届四中全会审议通过的“十五五”规划建议,明确提出“高标准建设海南自由贸易港”。

+

在中国的最南端,新时代全面深化改革开放的故事正不断书写。

+

|出品人:俞岚

+

|总策划:周锐

+

|统筹:马学玲 阚枫

+

|执笔:袁秀月

+

|校对:孙静波

+

|视觉:徐洋 雷宇竺

+

|中国新闻网“习言道”工作室出品

+

|中国互联网发展基金会中国正能量网络传播专项基金支持

+
+
(责编:白宇、卫嘉)
+

分享让更多人看到

+
+ + +
+ +
+ + +
+ +
+ +
+ +
+ + + + +
+
+ +
+
+ +
+
+
+ + + +
返回顶部
+ + + + + + + + + + + + + \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/search.sh b/schoolNewsCrawler/crawler/search.sh new file mode 100644 index 0000000..e7a4570 --- /dev/null +++ b/schoolNewsCrawler/crawler/search.sh @@ -0,0 +1 @@ +curl 'http://search.people.cn/search-platform/front/search' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: zh-CN,zh;q=0.9' -H 'Content-Type: application/json;charset=UTF-8' -b 'wdcid=05a6de97766c4599; sso_c=0; sfr=1; __jsluid_h=e16169886db91bc1035499568d07a448' -H 'Origin: http://search.people.cn' -H 'Proxy-Connection: keep-alive' -H 'Referer: http://search.people.cn/s/?keyword=%E8%A7%86%E9%A2%91%E6%96%B0%E9%97%BB&st=5&_=1762584848128' -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36' --data-raw '{"key":"视频新闻","page":1,"limit":10,"hasTitle":true,"hasContent":true,"isFuzzy":true,"type":5,"sortType":2,"startTime":0,"endTime":0}' --insecure \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/test_crawler.ipynb b/schoolNewsCrawler/crawler/test_crawler.ipynb new file mode 100644 index 0000000..3f7b913 --- /dev/null +++ b/schoolNewsCrawler/crawler/test_crawler.ipynb @@ -0,0 +1,334 @@ +{ + "cells": [ + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "# 爬虫测试 Notebook\n", + "用于测试人民日报爬虫功能\n", + "\n", + "## 1. 导入依赖" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "项目根目录: f:\\Project\\schoolNews\\schoolNewsCrawler\n", + "✓ 已启用自动重载模块功能 - 修改 .py 文件后会自动生效\n" + ] + } + ], + "source": [ + "# 自动重载模块(当文件修改后自动刷新)\n", + "%reload_ext autoreload\n", + "%autoreload 2\n", + "\n", + "import sys\n", + "import os\n", + "\n", + "# 先添加项目根目录到路径(必须在导入之前)\n", + "project_root = os.path.abspath(os.path.join(os.getcwd(), '..'))\n", + "if project_root not in sys.path:\n", + " sys.path.insert(0, project_root)\n", + "\n", + "# 然后再导入模块\n", + "from crawler.RmrbCrawler import RmrbCrawler\n", + "from crawler.BaseCrawler import NewsItem\n", + "from loguru import logger\n", + "import json\n", + "from pprint import pprint\n", + "\n", + "print(f\"项目根目录: {project_root}\")\n", + "print(\"✓ 已启用自动重载模块功能 - 修改 .py 文件后会自动生效\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 2. 初始化爬虫" + ] + }, + { + "cell_type": "code", + "execution_count": 5, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2025-11-10 11:09:38.821\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mcrawler.BaseCrawler\u001b[0m:\u001b[36m__init__\u001b[0m:\u001b[36m69\u001b[0m - \u001b[1m初始化爬虫: RmrbCrawler\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "爬虫初始化成功!\n", + "基础URL: http://www.people.com.cn\n", + "URLS: {'search': UrlConfig(url='http://search.people.cn/search-platform/front/search', params={'key': '', 'page': 1, 'limit': 10, 'hasTitle': True, 'hasContent': True, 'isFuzzy': True, 'type': 0, 'sortType': 2, 'startTime': 0, 'endTime': 0}, method='POST'), 'hot_point_rank': UrlConfig(url='http://search.people.cn/search-platform/front/searchRank', params={}, method='GET')}\n" + ] + } + ], + "source": [ + "# 创建爬虫实例\n", + "crawler = RmrbCrawler()\n", + "print(\"爬虫初始化成功!\")\n", + "print(f\"基础URL: {crawler.config.base_url}\")\n", + "print(f\"URLS: {crawler.config.urls}\")\n" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2025-11-10 13:21:41.775\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mcrawler.BaseCrawler\u001b[0m:\u001b[36mfetch\u001b[0m:\u001b[36m84\u001b[0m - \u001b[1m请求URL: http://politics.people.com.cn/n1/2025/1110/c461001-40600372.html (尝试 1/3)\u001b[0m\n", + "\u001b[32m2025-11-10 13:21:41.908\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mcrawler.RmrbCrawler\u001b[0m:\u001b[36mparse_news_detail\u001b[0m:\u001b[36m301\u001b[0m - \u001b[1m成功解析新闻: 习言道|建好这个“港”,习近平有深远考量\u001b[0m\n" + ] + }, + { + "data": { + "text/plain": [ + "NewsItem(title='习言道|建好这个“港”,习近平有深远考量', contentRows=[{'tag': 'p', 'style': None, 'content': ''}, {'tag': 'img', 'style': 'text-align: center;', 'content': 'http://www.people.com.cn/mediafile/pic/BIG/20251110/20/9596092983742008100.jpg'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '中新网11月8日电 题:建好这个“港”,习近平有深远考量'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '党的二十届四中全会后首次到地方,习近平总书记来到了海南三亚。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '再有一个多月,12月18日,海南自由贸易港将正式启动全岛封关。11月6日,在听取海南自由贸易港建设工作汇报时,习近平总书记强调,各级各有关方面要精心准备,确保平稳有序。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '对于自由贸易港建设,总书记一直寄予厚望。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '20世纪80年代,在厦门工作期间,习近平同志就曾牵头研究自由贸易港问题并将部分政策付诸实施。彼时,中国开放的大门刚刚打开。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '多年后,这一任务交到了海南手中。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '为什么是海南?从客观条件看,海南是我国最大的经济特区,地理位置独特,拥有全国最好的生态环境,同时又是相对独立的地理单元,具有成为全国改革开放试验田的独特优势。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '从历史看,海南之所以能从一个边陲海岛发展成为我国改革开放的重要窗口,正是得益于深化改革、扩大开放。建设自贸港,是海南开放发展道路的延续,也是面向未来发展的需要。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '从现实看,作为引领我国新时代对外开放的鲜明旗帜,海南自贸港建设不仅事关海南自身发展,更关乎中国改革开放全局。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '“由海南来完成这项历史性任务,这也是中国特色社会主义经济特区建设的一个战略安排,不断摸索、大胆试验,现在蹚出来一条路子。”2022年在海南考察时,对于海南自贸港建设的未来,习近平总书记曾饱含期待。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '只有敢于走别人没有走过的路,才能收获别样的风景。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '从2018年党中央决定支持海南全岛建设自由贸易试验区,到2020年《海南自由贸易港建设总体方案》发布,再到海南自贸港连续7年被写入政府工作报告……一系列顶层设计推动海南自贸港建设取得重要阶段性成效,为启动全岛封关运作打下坚实基础。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '美丽海岛持续释放活力,海南外贸连续5年增长,累计176个国家和地区在此投资。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '这次在海南,习近平总书记再次强调海南自贸港的定位——'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '“高标准建设海南自由贸易港,主要目的是促进海南高质量发展,助力全国构建新发展格局。”'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '“建设海南自由贸易港的战略目标,就是要把海南自由贸易港打造成为引领我国新时代对外开放的重要门户。”'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '从海南到全国,从中国到世界,总书记点明中国特色自由贸易港的重要使命与历史方位。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '此次,在海南自贸港将迈入全岛封关运作新阶段之际,总书记再次作出新部署。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '“进一步提高贸易投资自由化便利化水平”“着力打造市场化法治化国际化一流营商环境”“越是扩大开放,越要统筹发展和安全”……有方向指引,有具体要求,也有深远考量。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '前不久,党的二十届四中全会审议通过的“十五五”规划建议,明确提出“高标准建设海南自由贸易港”。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '在中国的最南端,新时代全面深化改革开放的故事正不断书写。'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|出品人:俞岚'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|总策划:周锐'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|统筹:马学玲 阚枫'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|执笔:袁秀月'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|校对:孙静波'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|视觉:徐洋 雷宇竺'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|中国新闻网“习言道”工作室出品'}, {'tag': 'p', 'style': 'text-indent: 2em;', 'content': '|中国互联网发展基金会中国正能量网络传播专项基金支持'}, {'tag': 'img', 'style': None, 'content': 'http://www.people.com.cn/img/2020wbc/imgs/share.png'}], url='http://politics.people.com.cn/n1/2025/1110/c461001-40600372.html', publishTime='2025年11月10日09:26', author='责编:白宇、卫嘉', source='中国新闻网', category='')" + ] + }, + "execution_count": 11, + "metadata": {}, + "output_type": "execute_result" + } + ], + "source": [ + "crawler.parse_news_detail(\"http://politics.people.com.cn/n1/2025/1110/c461001-40600372.html\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 3. 测试搜索功能" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stderr", + "output_type": "stream", + "text": [ + "\u001b[32m2025-11-08 17:21:50.827\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mcrawler.BaseCrawler\u001b[0m:\u001b[36mfetch\u001b[0m:\u001b[36m86\u001b[0m - \u001b[1m请求URL: http://search.people.cn/search-platform/front/search (尝试 1/3)\u001b[0m\n", + "\u001b[32m2025-11-08 17:21:50.913\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mcrawler.RmrbCrawler\u001b[0m:\u001b[36msearch\u001b[0m:\u001b[36m88\u001b[0m - \u001b[1m搜索响应: {'code': '0', 'data': {'records': [{'author': '', 'belongsName': '传媒', 'belongsId': '[\"14677\"]', 'content': '根据《中国新闻奖评选办法》和中国广播电视社会组织联合会通知,现对人民日报社推荐参加第35届中国新闻奖音视频新闻访谈、音视频新闻直播初评的4件作品予以公示。 公示期为2025年4月3日至4月10日。如有不同意见,可通过电话或电子邮件等方式发表评议意见,逾期不再受理。电话:010-65363945 邮箱:xwpx@people.cn 人民日报社 2025年4月3日 作品目录: 音视频新闻访谈3件: 巴黎奥运连麦丨对话“百米飞鱼”潘展乐:干进46秒,说到做到 两会零时差|以自身发展推动世界发展,中国提供了宝贵经验 两会面对面丨费俊龙对话叶聪:上天入海背后的故事 音视频新闻直播', 'contentOriginal': '根据《中国新闻奖评选办法》和中国广播电视社会组织联合会通知,现对人民日报社推荐参加第35届中国新闻奖音视频新闻访谈、音视频新闻直播初评的4件作品予以公示。 公示期为2025年4月3日至4月10日。如有不同意见,可通过电话或电子邮件等方式发表评议意见,逾期不再受理。 电话:010-65363945 邮箱:xwpx@people.cn 人民日报社 2025年4月3日 作品目录: 音视频新闻访谈3件: 巴黎奥运连麦丨对话“百米飞鱼”潘展乐:干进46秒,说到做到 两会零时差|以自身发展推动世界发展,中国提供了宝贵经验 两会面对面丨费俊龙对话叶聪:上天入海背后的故事 音视频新闻直播1件: 徒步54公里的思政课,坚守29年的薪火传承', 'displayTime': 1743670375000, 'domain': 'media.people.com.cn', 'editor': '王连香', 'hasImg': 0, 'hasVideo': 0, 'id': 1000040453328, 'imageUrl': None, 'inputTime': 1743670376000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '人民网#传媒', 'originUrl': '', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40453328, 'contentId': 40453328, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '人民日报社推荐参加第35届中国新闻奖音视频新闻访谈、 音视频新闻直播初评作品的公示', 'url': 'http://media.people.com.cn/n1/2025/0403/c14677-40453328.html', 'originName': '人民网'}, {'author': '', 'belongsName': '韩国频道#滚动#社会', 'belongsId': '[\"407366\",\"407862\",\"407864\"]', 'content': '韩国《朝鲜日报》4月23日文章,原题:成为利用假新闻牟利和政治两极化温床的网络视频平台 距离美国网络视频平台YouTube上传第一条视频已经过去了20年,其危害和副作用日益暴露。这里充斥着假新闻和有害信息,成为了助长政治两极化与社会矛盾和分裂的温床。一旦发生与名人相关的性骚扰、外遇、离婚、暴力、死亡事件,这些主播就会出现,用未经验证的质疑和虚假信息制作并上传视频,通过恐吓、威胁勒索巨额钱财。该平台算法只筛选符合用户喜好的刺激性内容——不是均衡推荐视频,而是不断引导人观看极端偏向的视频。借助仇恨、暴力、煽动性的视频助长严重的确证偏见。每个政治集会或示威现场,都有几十名政治视频主播。这些人制造的假新闻的弊端和政治两极化、社会矛盾的副作用,难以进行计算。 想阻止这种情况的发生,首先需要Youtube母公司谷歌内部进行限制和自我净化的努力。变成了赚钱手段的平台算法也需要进行改进。我们应该建立防止网络视频平台假新闻和偏见视频传播的制度机制。 来源:环球时报', 'contentOriginal': '韩国《朝鲜日报》4月23日文章,原题:成为利用假新闻牟利和政治两极化温床的网络视频平台 距离美国网络视频平台YouTube上传第一条视频已经过去了20年,其危害和副作用日益暴露。这里充斥着假新闻和有害信息,成为了助长政治两极化与社会矛盾和分裂的温床。问卷调查显示,62%的人认为其是“假新闻的生成主体”,压倒性地排在榜首。在假新闻传播渠道的选项里,该平台占66%。不少主播通过这种方式赚钱,政治人物从中获得政治利益,却并不承担责任。 订阅者为100万人左右的政治Youtube主播通过超级聊天赞助和点击量,每月能收益几千万韩元(1000万韩元约合5万元人民币)。报道清潭洞酒宴的主播每天赚取了2000万韩元以上。即使被起诉,收入也多于赔偿金,所以他们并不畏惧。一旦发生与名人相关的性骚扰、外遇、离婚、暴力、死亡事件,这些主播就会出现,用未经验证的质疑和虚假信息制作并上传视频,通过恐吓、威胁勒索巨额钱财。该平台算法只筛选符合用户喜好的刺激性内容——不是均衡推荐视频,而是不断引导人观看极端偏向的视频。借助仇恨、暴力、煽动性的视频助长严重的确证偏见。 网络视频平台的极端内容和假新闻对2021年美国攻占国会和暴动事件等产生了很大影响。每个政治集会或示威现场,都有几十名政治视频主播。这些人制造的假新闻的弊端和政治两极化、社会矛盾的副作用,难以进行计算。 想阻止这种情况的发生,首先需要Youtube母公司谷歌内部进行限制和自我净化的努力。变成了赚钱手段的平台算法也需要进行改进。还需要建立政治圈、市民团体、学术界、媒体等共同参与的社会验证机构。我们应该建立防止网络视频平台假新闻和偏见视频传播的制度机制。 来源:环球时报', 'displayTime': 1745897396000, 'domain': 'korea.people.com.cn', 'editor': '吴三叶', 'hasImg': 0, 'hasVideo': 0, 'id': 1000040470783, 'imageUrl': None, 'inputTime': 1745897396000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '人民网#韩国频道', 'originUrl': '', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40470783, 'contentId': 40470783, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '韩媒:美网络视频平台成假新闻温床', 'url': 'http://korea.people.com.cn/n1/2025/0429/c407366-40470783.html', 'originName': '\\u3000\\u3000'}, {'author': '', 'belongsName': '#梅里时评#', 'belongsId': '[\"372441\"]', 'content': '\\u3000\\u3000近日,一些短视频新闻频频“翻车”,对媒体公信力和网民媒介素养提出了新的挑战。9月1日,湖南一宝妈上传了一段双胞胎兄弟在肚子里打架的视频,引发网友关注。据视频显示,双胞胎兄弟在肚子里的时候就互不相让,在妈妈肚子里“拳打脚踢”,妈妈的肚子也跟着起伏变化,果然,双胞胎出生后身上就到处是淤青。但在视频引发热议后,就有专家辟谣,原来,大多数哺乳动物都具备学习游泳的能力。 \\u3000\\u3000类似的短视频新闻“翻车”事件暴露出两个问题。一是网络媒体从短视频平台搬运视频现象严重,对新闻的审核存在疏漏,未经核实就发布报道,导致像“双胞胎在肚里打架出生后浑身淤青”这样违反医学常识、耸人听闻的新闻误导大众。此外,一些新闻还存在虚假内容拼接现象。某些纯属娱乐的视频,却被媒体当成新闻真实事件报道出来,这难免会最终“翻车”。 \\u3000\\u3000二是网民对网络视频的判断能力存在偏差,面对似是而非的视频内容存在盲目相信、胡乱猜测等行为,网民的媒介素养和科学素质有待提升。笔者建议,网络平台要做到严格按照新闻采编规范进行新闻采访报道,并对新闻内容进行严格把关与核实,不可照搬短视频平台未经核实的内容。新闻媒体在普及科学的新闻内容时,一定要慎之又慎,以免误导大众,为此造成虚假新闻传播泛滥,导致媒体公信力缺失。希望相关部门的举措,可以减少短视频新闻“翻车”现象的发生,促使媒体公信力和网民媒介素养不断提升。(李华锡)', 'contentOriginal': '

\\u3000\\u3000近日,一些短视频新闻频频“翻车”,对媒体公信力和网民媒介素养提出了新的挑战。9月1日,湖南一宝妈上传了一段双胞胎兄弟在肚子里打架的视频,引发网友关注。据视频显示,双胞胎兄弟在肚子里的时候就互不相让,在妈妈肚子里“拳打脚踢”,妈妈的肚子也跟着起伏变化,果然,双胞胎出生后身上就到处是淤青。该视频被媒体报道后登上热搜,但在9月4日,产科医生辟谣了,原来,双胞胎在肚里打架的情况,不大可能发生,网友对很多医学常识缺乏了解。8月30日,有海南三亚居民拍摄到一只猴子在海中游泳。拍摄者表示:当时看到猴子在海里游泳就很惊讶,网友也开始怀疑这是不是传说中的“水猴子”。但在视频引发热议后,就有专家辟谣,原来,大多数哺乳动物都具备学习游泳的能力。

\\n

\\u3000\\u3000类似的短视频新闻“翻车”事件暴露出两个问题。一是网络媒体从短视频平台搬运视频现象严重,对新闻的审核存在疏漏,未经核实就发布报道,导致像“双胞胎在肚里打架出生后浑身淤青”这样违反医学常识、耸人听闻的新闻误导大众。此外,一些新闻还存在虚假内容拼接现象。某些纯属娱乐的视频,却被媒体当成新闻真实事件报道出来,这难免会最终“翻车”。

\\n

\\u3000\\u3000二是网民对网络视频的判断能力存在偏差,面对似是而非的视频内容存在盲目相信、胡乱猜测等行为,网民的媒介素养和科学素质有待提升。如“水猴子”事件中,如果网民有一定的科学常识,就不会随意相信网络上各种“水猴子”传言。如在“双胞胎在肚里打架出生后浑身淤青”事件中,如果网民对怀孕知识有一定的了解,或及时向产科医生求证,提出质疑,就不会造成上述令人啼笑皆非的事情。

\\n

\\u3000\\u3000那么,该如何保证媒体公信力、提升网民媒介素养呢?笔者建议,网络平台要做到严格按照新闻采编规范进行新闻采访报道,并对新闻内容进行严格把关与核实,不可照搬短视频平台未经核实的内容。新闻媒体在普及科学的新闻内容时,一定要慎之又慎,以免误导大众,为此造成虚假新闻传播泛滥,导致媒体公信力缺失。与此同时,网民也要加强自身的媒介素养和科学素质,自觉学习相关知识,提高认知水平和判断能力,不可轻信虚假信息,面对谣言要保留证据并及时举报,做到不信谣、不传谣,不要再让这些所谓的“新闻”哗众取宠。

\\n

\\u3000\\u3000值得注意的是,近日,中共中央办公厅、国务院办公厅印发了《关于新时代进一步加强科学技术普及工作的意见》,对公民自觉提升科学素质、抵制伪科学、反科学等不良现象提出了新的要求。希望相关部门的举措,可以减少短视频新闻“翻车”现象的发生,促使媒体公信力和网民媒介素养不断提升。(李华锡)

', 'displayTime': 1662510209000, 'domain': 'yn.people.com.cn', 'editor': '木胜玉', 'hasImg': 0, 'hasVideo': 0, 'id': 2000040114019, 'imageUrl': None, 'inputTime': 1662510210000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': '', 'newsJson': None, 'originNodeRname': '人民网#云南频道#梅里时评', 'originUrl': 'http://zqb.cyol.com/html/2022-09/07/nw.D110000zgqnb_20220907_3-07.htm ', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 2, 'sourceId': 40114019, 'contentId': 40114019, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '短视频新闻频“翻车” 挑战媒介素养', 'url': 'http://yn.people.com.cn/n2/2022/0907/c372441-40114019.html', 'originName': '中国青年报'}, {'author': '', 'belongsName': '日本频道#社会#滚动新闻#图片库', 'belongsId': '[\"35421\",\"35467\",\"368232\",\"368567\"]', 'content': '\\u3000\\u3000中新社湖南芷江8月21日电 (付敬懿 黄建建)位于湖南芷江的中国人民抗日战争胜利受降纪念馆21日公布《日本投降》新闻纪录片原始视频视频摄制于1945年,由美国国家档案馆提供。 \\u3000\\u30008月21日,拍摄于1945年的《日本投降》新闻纪录片原始视频在湖南芷江公布。\\u3000付敬懿 摄 \\u3000\\u3000该视频展现了芷江受降作为东方主战场胜利的标志性事件,以及日本投降开启亚太战场胜利序幕的历史意义,为研究中国抗日战争和世界反法西斯战争提供了珍贵的一手资料。 \\u3000\\u30002014年,中国人民抗日战争胜利受降纪念馆曾公布日本在芷江向中国投降的原始视频资料,记录了日本投降代表从下飞机到签署投降备忘录的全过程。 \\u3000\\u3000此次新公布的原始视频,从更宏观的视角展现中国抗日战争与世界反法西斯战争的紧密联系。中国人民抗日战争胜利受降纪念馆馆长吴建宏表示,这些视频资料将让更多人了解历史真相,激励当代人铭记历史,珍惜来之不易的和平。 \\u3000\\u3000当日,纪念馆还公布了一批由抗战老兵捐赠的历史照片、作战地图等。(完)', 'contentOriginal': '

\\u3000\\u3000中新社湖南芷江8月21日电 (付敬懿 黄建建)位于湖南芷江的中国人民抗日战争胜利受降纪念馆21日公布《日本投降》新闻纪录片原始视频,视频摄制于1945年,由美国国家档案馆提供。

\"\"

\\u3000\\u30008月21日,拍摄于1945年的《日本投降》新闻纪录片原始视频在湖南芷江公布。\\u3000付敬懿 摄

\\u3000\\u3000该视频展现了芷江受降作为东方主战场胜利的标志性事件,以及日本投降开启亚太战场胜利序幕的历史意义,为研究中国抗日战争和世界反法西斯战争提供了珍贵的一手资料。

\\u3000\\u30002014年,中国人民抗日战争胜利受降纪念馆曾公布日本在芷江向中国投降的原始视频资料,记录了日本投降代表从下飞机到签署投降备忘录的全过程。

\\u3000\\u3000此次新公布的原始视频,从更宏观的视角展现中国抗日战争与世界反法西斯战争的紧密联系。中国人民抗日战争胜利受降纪念馆馆长吴建宏表示,这些视频资料将让更多人了解历史真相,激励当代人铭记历史,珍惜来之不易的和平。

\\u3000\\u3000当日,纪念馆还公布了一批由抗战老兵捐赠的历史照片、作战地图等。(完)

', 'displayTime': 1755826214000, 'domain': 'japan.people.com.cn', 'editor': '许文金', 'hasImg': 1, 'hasVideo': 0, 'id': 1000040548000, 'imageUrl': 'http://japan.people.com.cn/mediafile/pic/20250822/56/592998228316100220.jpg', 'inputTime': 1755826214000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '人民网#日本频道', 'originUrl': 'http://www.chinanews.com.cn/gn/2025/08-21/10468902.shtml', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40548000, 'contentId': 40548000, 'sourcetitle': '(抗战胜利80周年)《日本投降》新闻纪录片原始视频公布', 'sourceType': 1, 'subtitle': '', 'title': '(抗战胜利80周年)《日本投降》新闻纪录片原始视频公布', 'url': 'http://japan.people.com.cn/n1/2025/0822/c35421-40548000.html', 'originName': '中国新闻网'}, {'author': '', 'belongsName': '中日万象', 'belongsId': '[\"368507\"]', 'content': '\\u3000\\u3000中新社湖南芷江8月21日电 (付敬懿 黄建建)位于湖南芷江的中国人民抗日战争胜利受降纪念馆21日公布《日本投降》新闻纪录片原始视频视频摄制于1945年,由美国国家档案馆提供。 \\u3000\\u30008月21日,拍摄于1945年的《日本投降》新闻纪录片原始视频在湖南芷江公布。\\u3000付敬懿 摄 \\u3000\\u3000该视频展现了芷江受降作为东方主战场胜利的标志性事件,以及日本投降开启亚太战场胜利序幕的历史意义,为研究中国抗日战争和世界反法西斯战争提供了珍贵的一手资料。 \\u3000\\u30002014年,中国人民抗日战争胜利受降纪念馆曾公布日本在芷江向中国投降的原始视频资料,记录了日本投降代表从下飞机到签署投降备忘录的全过程。 \\u3000\\u3000此次新公布的原始视频,从更宏观的视角展现中国抗日战争与世界反法西斯战争的紧密联系。中国人民抗日战争胜利受降纪念馆馆长吴建宏表示,这些视频资料将让更多人了解历史真相,激励当代人铭记历史,珍惜来之不易的和平。 \\u3000\\u3000当日,纪念馆还公布了一批由抗战老兵捐赠的历史照片、作战地图等。(完)', 'contentOriginal': '

\\u3000\\u3000中新社湖南芷江8月21日电 (付敬懿 黄建建)位于湖南芷江的中国人民抗日战争胜利受降纪念馆21日公布《日本投降》新闻纪录片原始视频,视频摄制于1945年,由美国国家档案馆提供。

\"\"

\\u3000\\u30008月21日,拍摄于1945年的《日本投降》新闻纪录片原始视频在湖南芷江公布。\\u3000付敬懿 摄

\\u3000\\u3000该视频展现了芷江受降作为东方主战场胜利的标志性事件,以及日本投降开启亚太战场胜利序幕的历史意义,为研究中国抗日战争和世界反法西斯战争提供了珍贵的一手资料。

\\u3000\\u30002014年,中国人民抗日战争胜利受降纪念馆曾公布日本在芷江向中国投降的原始视频资料,记录了日本投降代表从下飞机到签署投降备忘录的全过程。

\\u3000\\u3000此次新公布的原始视频,从更宏观的视角展现中国抗日战争与世界反法西斯战争的紧密联系。中国人民抗日战争胜利受降纪念馆馆长吴建宏表示,这些视频资料将让更多人了解历史真相,激励当代人铭记历史,珍惜来之不易的和平。

\\u3000\\u3000当日,纪念馆还公布了一批由抗战老兵捐赠的历史照片、作战地图等。(完)

', 'displayTime': 1755852269000, 'domain': 'cjkeizai.j.people.com.cn', 'editor': '张璐璐', 'hasImg': 1, 'hasVideo': 0, 'id': 1000040548254, 'imageUrl': 'http://cjkeizai.j.people.com.cn/mediafile/pic/20250822/56/592998228316100220.jpg', 'inputTime': 1755852270000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '人民网#日本频道#中日经济交流网#中日万象', 'originUrl': 'http://www.chinanews.com.cn/gn/2025/08-21/10468902.shtml', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40548254, 'contentId': 40548254, 'sourcetitle': '(抗战胜利80周年)《日本投降》新闻纪录片原始视频公布', 'sourceType': 1, 'subtitle': '', 'title': '(抗战胜利80周年)《日本投降》新闻纪录片原始视频公布', 'url': 'http://cjkeizai.j.people.com.cn/n1/2025/0822/c368507-40548254.html', 'originName': '中国新闻网'}, {'author': '', 'belongsName': '#传媒#', 'belongsId': '[\"14677\"]', 'content': '根据《中国新闻奖评选办法》和中国广播电视社会组织联合会通知,现对人民日报社推荐参加第34届中国新闻奖音视频新闻访谈、音视频新闻直播初评的4件作品予以公示。公示期为2024年4月12日至4月18日,共5个工作日。如有不同意见,可于4月18日17时前通过书面、电话等方式反映。', 'contentOriginal': '

根据《中国新闻奖评选办法》和中国广播电视社会组织联合会通知,现对人民日报社推荐参加第34届中国新闻奖音视频新闻访谈、音视频新闻直播初评的4件作品予以公示。公示期为2024年4月12日至4月18日,共5个工作日。如有不同意见,可于4月18日17时前通过书面、电话等方式反映。

\\n

电话:010-65363945

\\n

邮箱:xwpx@people.cn

\\n

人民日报社

\\n

2024年4月12日

\\n

新媒体音视频访谈4件:

\\n

1.2023全国两会·两会夜话第三期:身边的民主 管用的民主

\\n

2.两会零时差|老挝驻华大使:中国式现代化具有重要的世界意义

\\n

3.“思想的力量”网络公开课

\\n

4.【大使眼里的元首外交⑩】“无论是雨是晴,巴中始终站在一起”

', 'displayTime': 1712927181000, 'domain': 'media.people.com.cn', 'editor': '白宇', 'hasImg': 0, 'hasVideo': 0, 'id': 1000040215113, 'imageUrl': None, 'inputTime': 1712927181000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': '', 'newsJson': None, 'originNodeRname': '人民网#传媒', 'originUrl': '', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40215113, 'contentId': 40215113, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '人民日报社参加第34届中国新闻奖音视频新闻访谈、音视频新闻直播初评作品公示', 'url': 'http://media.people.com.cn/n1/2024/0412/c14677-40215113.html', 'originName': '人民网'}, {'author': '', 'belongsName': '图片报道', 'belongsId': '[\"460959\"]', 'content': '国务院新闻办新闻局局长、新闻发言人寿小丽邀请记者提问 中国网 郑亮', 'contentOriginal': '

\"\"

国务院新闻办新闻局局长、新闻发言人寿小丽邀请记者提问

中国网 郑亮

', 'displayTime': 1756351952000, 'domain': 'cpc.people.com.cn', 'editor': '王珂园', 'hasImg': 1, 'hasVideo': 0, 'id': 1000040551973, 'imageUrl': 'http://cpc.people.com.cn/NMediaFile/2025/0828/MAIN1756351942867XWO5F4ZOO1.jpg', 'inputTime': 1756351952000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '中国共产党新闻网#专题报道#纪念中国人民抗日战争暨世界反法西斯战争胜利80周年#本网直播#中国人民抗日战争暨世界反法西斯战争胜利80周年纪念活动新闻中心第一场记者招待会#图片报道', 'originUrl': 'http://www.china.com.cn/zhibo/content_118045249.htm', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40551973, 'contentId': 40551973, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '国务院新闻新闻局局长、新闻发言人寿小丽邀请记者提问', 'url': 'http://cpc.people.com.cn/n1/2025/0828/c460959-40551973.html', 'originName': '中国网'}, {'author': '', 'belongsName': '图片报道', 'belongsId': '[\"460961\"]', 'content': '国务院新闻办新闻局局长、新闻发言人寿小丽邀请记者提问 中国网 郑亮', 'contentOriginal': '

\"\"

国务院新闻办新闻局局长、新闻发言人寿小丽邀请记者提问

中国网 郑亮

', 'displayTime': 1756437257000, 'domain': 'cpc.people.com.cn', 'editor': '王珂园', 'hasImg': 1, 'hasVideo': 0, 'id': 1000040552779, 'imageUrl': 'http://cpc.people.com.cn/NMediaFile/2025/0829/MAIN1756437252763C7Q7C4P40A.jpg', 'inputTime': 1756437258000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '中国共产党新闻网#专题报道#纪念中国人民抗日战争暨世界反法西斯战争胜利80周年#本网直播#中国人民抗日战争暨世界反法西斯战争胜利80周年纪念活动新闻中心第二场记者招待会#图片报道', 'originUrl': 'http://www.china.com.cn/zhibo/content_118047028.htm', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40552779, 'contentId': 40552779, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '国务院新闻新闻局局长、新闻发言人寿小丽邀请记者提问', 'url': 'http://cpc.people.com.cn/n1/2025/0829/c460961-40552779.html', 'originName': '中国网'}, {'author': '', 'belongsName': '图片报道', 'belongsId': '[\"460959\"]', 'content': '国务院新闻办新闻局局长、新闻发言人寿小丽主持记者招待会 中国网 郑亮', 'contentOriginal': '

\"\"

国务院新闻办新闻局局长、新闻发言人寿小丽主持记者招待会

中国网 郑亮

', 'displayTime': 1756351856000, 'domain': 'cpc.people.com.cn', 'editor': '王珂园', 'hasImg': 1, 'hasVideo': 0, 'id': 1000040551971, 'imageUrl': 'http://cpc.people.com.cn/NMediaFile/2025/0828/MAIN1756351844858SZKOZ76H2O.jpg', 'inputTime': 1756351857000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '中国共产党新闻网#专题报道#纪念中国人民抗日战争暨世界反法西斯战争胜利80周年#本网直播#中国人民抗日战争暨世界反法西斯战争胜利80周年纪念活动新闻中心第一场记者招待会#图片报道', 'originUrl': 'http://www.china.com.cn/zhibo/content_118045249.htm', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40551971, 'contentId': 40551971, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '国务院新闻新闻局局长、新闻发言人寿小丽主持记者招待会', 'url': 'http://cpc.people.com.cn/n1/2025/0828/c460959-40551971.html', 'originName': '中国网'}, {'author': '', 'belongsName': '图片报道', 'belongsId': '[\"460961\"]', 'content': '国务院新闻办新闻局局长、新闻发言人寿小丽主持记者招待会 中国网 郑亮', 'contentOriginal': '

\"\"

国务院新闻办新闻局局长、新闻发言人寿小丽主持记者招待会

中国网 郑亮

', 'displayTime': 1756437535000, 'domain': 'cpc.people.com.cn', 'editor': '王珂园', 'hasImg': 1, 'hasVideo': 0, 'id': 1000040552781, 'imageUrl': 'http://cpc.people.com.cn/NMediaFile/2025/0829/MAIN1756437530762AIS3XWH62A.jpg', 'inputTime': 1756437535000, 'isDisclosed': None, 'isElited': None, 'isFixed': None, 'isOfficial': None, 'isRecommend': None, 'keyword': None, 'newsJson': None, 'originNodeRname': '中国共产党新闻网#专题报道#纪念中国人民抗日战争暨世界反法西斯战争胜利80周年#本网直播#中国人民抗日战争暨世界反法西斯战争胜利80周年纪念活动新闻中心第二场记者招待会#图片报道', 'originUrl': 'http://www.china.com.cn/zhibo/content_118047028.htm', 'originalName': None, 'originalType': None, 'pretitle': '', 'shorttitle': '', 'source': 1, 'sourceId': 40552781, 'contentId': 40552781, 'sourcetitle': '', 'sourceType': 1, 'subtitle': '', 'title': '国务院新闻新闻局局长、新闻发言人寿小丽主持记者招待会', 'url': 'http://cpc.people.com.cn/n1/2025/0829/c460961-40552781.html', 'originName': '中国网'}], 'total': 15882, 'size': 10, 'current': 1, 'orders': [], 'optimizeCountSql': True, 'hitCount': False, 'countId': None, 'maxLimit': None, 'searchCount': True, 'pages': 1589}, 'server_time': 1762593711}\u001b[0m\n", + "\u001b[32m2025-11-08 17:21:50.914\u001b[0m | \u001b[1mINFO \u001b[0m | \u001b[36mcrawler.RmrbCrawler\u001b[0m:\u001b[36msearch\u001b[0m:\u001b[36m113\u001b[0m - \u001b[1m搜索到 0 条新闻\u001b[0m\n" + ] + }, + { + "name": "stdout", + "output_type": "stream", + "text": [ + "\n", + "搜索关键词: 视频新闻\n", + "搜索结果数量: 0\n" + ] + } + ], + "source": [ + "# 测试搜索\n", + "search_keyword = \"视频新闻\"\n", + "search_results = crawler.search(key=search_keyword, page=1, limit=10, news_type=0)\n", + "\n", + "print(f\"\\n搜索关键词: {search_keyword}\")\n", + "print(f\"搜索结果数量: {len(search_results)}\")\n", + "\n", + "if search_results:\n", + " for i, news in enumerate(search_results, 1):\n", + " print(f\"\\n{i}. {news.title}\")\n", + " print(f\" 链接: {news.url}\")\n", + " print(f\" 时间: {news.publish_time}\")" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 4. 测试爬取列表页" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 爬取新闻列表\n", + "category = \"politics\" # 可选: politics, society, world, finance, tech, culture, education\n", + "limit = 5\n", + "\n", + "news_list = crawler.crawl(category=category, limit=limit)\n", + "\n", + "print(f\"\\n爬取分类: {category}\")\n", + "print(f\"爬取数量: {len(news_list)}/{limit}\")\n", + "\n", + "# 显示结果\n", + "for i, news in enumerate(news_list, 1):\n", + " print(f\"\\n{i}. {news.title}\")\n", + " print(f\" 链接: {news.url}\")\n", + " print(f\" 来源: {news.source}\")\n", + " print(f\" 时间: {news.publish_time}\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 5. 测试解析单个新闻详情" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 测试解析单个新闻页面\n", + "test_url = \"http://www.people.com.cn/\" # 替换为实际的新闻URL\n", + "\n", + "# 如果之前爬取有结果,使用第一条新闻的URL\n", + "if news_list:\n", + " test_url = news_list[0].url\n", + "\n", + "print(f\"测试URL: {test_url}\")\n", + "news_detail = crawler.parse_news_detail(test_url)\n", + "\n", + "if news_detail:\n", + " print(\"\\n新闻详情:\")\n", + " print(f\"标题: {news_detail.title}\")\n", + " print(f\"作者: {news_detail.author}\")\n", + " print(f\"时间: {news_detail.publish_time}\")\n", + " print(f\"来源: {news_detail.source}\")\n", + " print(f\"图片数量: {len(news_detail.images)}\")\n", + " print(f\"\\n内容预览 (前200字):\")\n", + " print(news_detail.content[:200] if news_detail.content else \"无内容\")\n", + "else:\n", + " print(\"解析失败\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 6. 导出数据" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 将爬取的数据转换为字典列表\n", + "if news_list:\n", + " news_data = [news.model_dump() for news in news_list]\n", + " \n", + " # 保存为JSON文件\n", + " output_file = \"../output/test_news_from_notebook.json\"\n", + " os.makedirs(os.path.dirname(output_file), exist_ok=True)\n", + " \n", + " with open(output_file, 'w', encoding='utf-8') as f:\n", + " json.dump(news_data, f, ensure_ascii=False, indent=2)\n", + " \n", + " print(f\"数据已保存到: {output_file}\")\n", + " print(f\"总计: {len(news_data)} 条新闻\")\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 7. 数据统计分析" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "if news_list:\n", + " # 统计信息\n", + " total_news = len(news_list)\n", + " news_with_images = sum(1 for news in news_list if news.images)\n", + " news_with_author = sum(1 for news in news_list if news.author)\n", + " news_with_time = sum(1 for news in news_list if news.publish_time)\n", + " \n", + " print(\"=\" * 50)\n", + " print(\"爬取数据统计\")\n", + " print(\"=\" * 50)\n", + " print(f\"总新闻数量: {total_news}\")\n", + " print(f\"包含图片: {news_with_images} ({news_with_images/total_news*100:.1f}%)\")\n", + " print(f\"有作者信息: {news_with_author} ({news_with_author/total_news*100:.1f}%)\")\n", + " print(f\"有时间信息: {news_with_time} ({news_with_time/total_news*100:.1f}%)\")\n", + " \n", + " # 平均内容长度\n", + " avg_content_length = sum(len(news.content) for news in news_list) / total_news\n", + " print(f\"平均内容长度: {avg_content_length:.0f} 字符\")\n", + " \n", + " # 图片总数\n", + " total_images = sum(len(news.images) for news in news_list)\n", + " print(f\"图片总数: {total_images}\")\n", + " print(\"=\" * 50)\n" + ] + }, + { + "cell_type": "markdown", + "metadata": {}, + "source": [ + "## 8. 清理资源" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "# 关闭爬虫会话\n", + "crawler.close()\n", + "print(\"爬虫会话已关闭\")\n" + ] + } + ], + "metadata": { + "kernelspec": { + "display_name": "shoolNewsCrewer", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.10.19" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/schoolNewsCrawler/crawler/人民网界面结构.md b/schoolNewsCrawler/crawler/人民网界面结构.md new file mode 100644 index 0000000..fad38b5 --- /dev/null +++ b/schoolNewsCrawler/crawler/人民网界面结构.md @@ -0,0 +1,65 @@ +# 爬虫页面 + +## [人民网搜索](http://search.people.cn/) 热点排行 + +```python +CrawlerConfig( + base_url="http://www.people.com.cn", + urls={ + "search": UrlConfig( + url="http://search.people.cn/search-platform/front/search", + method="POST", + params={ + "key": "", + "page": 1, + "limit": 10, + "hasTitle": True, + "hasContent": True, + "isFuzzy": True, + "type": 0, # 0 所有,1 新闻,2 互动,3 报刊,4 图片,5 视频 + "sortType": 2, # 1 按相关度,2 按时间 + "startTime": 0, + "endTime": 0 + } + ), + "hot_point_rank": UrlConfig( + url="http://search.people.cn/search-platform/front/searchRank", + method="GET", + params={} + ) + }, + headers={ + 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/142.0.0.0 Safari/537.36', + 'Accept': 'application/json, text/plain, */*', + 'Accept-Language': 'zh-CN,zh;q=0.9', + 'Content-Type': 'application/json;charset=UTF-8' + } +) +``` + +## [精彩头条](http://www.people.com.cn/GB/59476/index.html) + +> 查询对应日期的所有精彩头条 +http://www.people.com.cn/GB/59476/review/yyyyMMdd.html + +一个html文件。里面包含了当天所有精彩新闻 + +## 一个新闻详情页html内数据结构 +```sh +--------------------------------------------------------------------------- +xxxx等导航栏 +--------------------------------------------------------------------------- +# 左右结构 col col-1 fr |col col-2 fr +新闻标题 h1 | 热门排行 rm_ranking cf +新闻作者 author cf | +时间、渠道 channel cf (col-1-1 fl) | +新闻内容(含img、video标签) rm_txt_con cf | 二维码 tjewm1 cf +img、video都是相对路径。拼接baseUrl +--------------------------------------------------------------------------- +``` + + +## [反腐](http://fanfu.people.com.cn/index1.html) +分页查询 http://fanfu.people.com.cn/index{page}.html +根据页数拼接get等待html。 +对里面的独立新闻链接访问。 再走独立详情页查询 \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/学习强国结构.md b/schoolNewsCrawler/crawler/学习强国结构.md new file mode 100644 index 0000000..768f5be --- /dev/null +++ b/schoolNewsCrawler/crawler/学习强国结构.md @@ -0,0 +1,47 @@ +# 学习强国 +## 搜索接口 +GET https://search.xuexi.cn/api/search +### 入参 +{ + "size": 15, # 每页返回数量 + "hid": "8rRCExvNOv8HUCnncajqG9x825v1u6a3", # 设备/会话ID + "client_version": "PC:0.0.9", # 客户端版本 + "page": 1, # 页码 + "query": "习近平", # 搜索关键词 (URL编码) + "program_id": 0, # 程序ID (0=全部) + "product_params": { # 产品参数 (JSON格式,需URL编码) + "time_filter": "all", # 时间过滤: all/day/week/month/year + "type_filter": "all", # 类型过滤: all/news(图文)/picture(图集)/video(视频)/book(书籍) + "sort_method": "integrated", # 排序方式: integrated(综合)/time(时间) + "search_method": "all" # 搜索方式: all/title/content + }, + "_t": 1762595495842 # 时间戳(毫秒) +} +### 返回数组内对象 +{ + "status": 0, + "message": "SUCCESS", + "data": { + "total": 919, + "pages": 20, + "list": [] + } +} + +{ + "summary": "", + "image": [ + "https://boot-img.xuexi.cn/image/1005/process/9cb21330294b46c780fd7a3a3d068e70.jpg" + ], + "show_time": "9个月前", + "item_id": "5787654603241390445", + "biz_type": "15", + "program_id": "0", + "title": "法语版|<em>习近平</em>春节前夕赴辽宁看望慰问基层干部群众", + "type": "kFiles", + "url": "https://article.xuexi.cn/articles/pdf/index.html?art_id=5787654603241390445", + "publish_time": "2025-01-25", + "show_source": "“学习强国”学习平台", + "biz_id": "5787654603241390445", + "desc": "" +} \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/首页头条--人民网.html b/schoolNewsCrawler/crawler/首页头条--人民网.html new file mode 100644 index 0000000..ff5859a --- /dev/null +++ b/schoolNewsCrawler/crawler/首页头条--人民网.html @@ -0,0 +1,327 @@ + + + + + + + + + + + +首页头条--人民网 + + + + + + + + + + + + +
+ + + + +
+ + + + + + +
+ + + + +
人民网—今日头条一览:2025年11月6日星期四 + + + + + +
新闻搜索
+ + + + + +

+ + + + +
[11月06日15:36]
+
+ + + + +
+
+ + + + +
+ + + + + + +
+ + + + + +

+ + + + + +
今日要闻 
+ + + + +
+
  • 中央党校(国家行政学院)举行2025年秋季学期第一批进修班毕业典礼 陈希出席
  • [2025年11月06日20:22]
  • 国务院任免国家工作人员
  • [2025年11月06日19:23]
  • 数读中国|看我国出入境政策"新利好"
    免税店政策"上新" 带你划重点
  • [2025年11月06日18:56]
  • 乌镇峰会|携手共筑数智未来——我国积极推进全球互联网发展治理
  • + [2025年11月06日19:06]
  • 泰国国王哇集拉隆功将访华 外交部介绍有关安排
  • [2025年11月06日16:51]
  • 外交部:敦促日方停止向"台独"分裂势力发出任何错误信号
  • [2025年11月06日18:21]
  • 水利部发布规范强化河湖管理保护
  • [2025年11月06日20:16]
  • 商务部:中方将不断优化许可流程 促进出口管制物项合规贸易
  • [2025年11月06日19:06]
  • 我国各类组织机构总量已达2.02亿家
  • [2025年11月06日20:16]
  • 重庆调整部分行政区划:设立两江新区,撤销江北区、渝北区
  • [2025年11月06日17:47]
  • 北京立冬日迎降水降温 多区确认将供热点火试运行
  • [2025年11月06日18:10]
  • 网友反映连霍高速酒玉段拥堵 甘肃酒泉:多措并举保畅通
  • [2025年11月06日21:33]
  • 十五运会|湖北队卫冕男子马拉松游泳冠军
  • [2025年11月06日21:33]
  • 格鲁吉亚外长博乔里什维利将访华
  • [2025年11月06日06:31]
  • 停止对原产于美国部分进口商品加征关税
    调整对原产于美国的进口商品加征关税
  • [2025年11月06日06:32]
  • 国台办:做好新时代对台工作,坚定不移推进祖国统一大业
  • [2025年11月06日06:42]
  • 向新逐"绿"我国新型能源体系加快构建
  • [2025年11月06日18:09]
  • 香港金管局发布"金融科技2030"愿景
  • [2025年11月06日06:43]
  • 乡村招商会 "村创"大舞台 搭好桥梁促振兴
  • [2025年11月06日06:28]
  • 东北省际高铁首次形成"O"形闭环
  • [2025年11月06日06:29]
  • 子午工程,立体监测日地空间天气 相信年轻人的聪明才智
  • + [2025年11月06日06:24]
  • 留言板·观豫|打通田埂"末梢"梗阻,须再加把劲
  • [2025年11月06日17:48]
  • 年产8000万条秋裤,小村里有大产业
  • [2025年11月06日07:04]
  • 寻油找气,如何给地球做高清"CT"
  • [2025年11月06日06:29]
  • 300元以下,难购真羽绒服?
  • [2025年11月06日06:31]
  • 人生的"午后时光"该怎样度过
  • [2025年11月06日06:30] + + + + + + + +
    + + + + + +
    + + + + +
    +
    + + + + +
    +
    +
    + + + + + + +
     人民网首页往日回顾
    + + + + +
    +
    +
    + +
     
    +
    +
    + + + + + + \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/20251106.html b/schoolNewsCrawler/crawler/首页头条--人民网_files/20251106.html new file mode 100644 index 0000000..d0cae67 --- /dev/null +++ b/schoolNewsCrawler/crawler/首页头条--人民网_files/20251106.html @@ -0,0 +1,325 @@ + + + + + + + + + + + +首页头条--人民网 + + + + + + + + + + + + +
    + + + + +
    + + + + + + +
    + + + + +
    人民网—今日头条一览:2025年11月6日星期四 + + + + + +
    新闻搜索
    + + + + + +

    + + + + +
    [11月06日15:36]
    +
    + + + + +
    +
    + + + + +
    + + + + + + +
    + + + + + +

    + + + + + +
    今日要闻 
    + + + + +
    +
  • 中央党校(国家行政学院)举行2025年秋季学期第一批进修班毕业典礼 陈希出席
  • [2025年11月06日20:22]
  • 国务院任免国家工作人员
  • [2025年11月06日19:23]
  • 数读中国|看我国出入境政策"新利好"
    免税店政策"上新" 带你划重点
  • [2025年11月06日18:56]
  • 乌镇峰会|携手共筑数智未来——我国积极推进全球互联网发展治理
  • + [2025年11月06日19:06]
  • 泰国国王哇集拉隆功将访华 外交部介绍有关安排
  • [2025年11月06日16:51]
  • 外交部:敦促日方停止向"台独"分裂势力发出任何错误信号
  • [2025年11月06日18:21]
  • 水利部发布规范强化河湖管理保护
  • [2025年11月06日20:16]
  • 商务部:中方将不断优化许可流程 促进出口管制物项合规贸易
  • [2025年11月06日19:06]
  • 我国各类组织机构总量已达2.02亿家
  • [2025年11月06日20:16]
  • 重庆调整部分行政区划:设立两江新区,撤销江北区、渝北区
  • [2025年11月06日17:47]
  • 北京立冬日迎降水降温 多区确认将供热点火试运行
  • [2025年11月06日18:10]
  • 网友反映连霍高速酒玉段拥堵 甘肃酒泉:多措并举保畅通
  • [2025年11月06日21:33]
  • 十五运会|湖北队卫冕男子马拉松游泳冠军
  • [2025年11月06日21:33]
  • 格鲁吉亚外长博乔里什维利将访华
  • [2025年11月06日06:31]
  • 停止对原产于美国部分进口商品加征关税
    调整对原产于美国的进口商品加征关税
  • [2025年11月06日06:32]
  • 国台办:做好新时代对台工作,坚定不移推进祖国统一大业
  • [2025年11月06日06:42]
  • 向新逐"绿"我国新型能源体系加快构建
  • [2025年11月06日18:09]
  • 香港金管局发布"金融科技2030"愿景
  • [2025年11月06日06:43]
  • 乡村招商会 "村创"大舞台 搭好桥梁促振兴
  • [2025年11月06日06:28]
  • 东北省际高铁首次形成"O"形闭环
  • [2025年11月06日06:29]
  • 子午工程,立体监测日地空间天气 相信年轻人的聪明才智
  • + [2025年11月06日06:24]
  • 留言板·观豫|打通田埂"末梢"梗阻,须再加把劲
  • [2025年11月06日17:48]
  • 年产8000万条秋裤,小村里有大产业
  • [2025年11月06日07:04]
  • 寻油找气,如何给地球做高清"CT"
  • [2025年11月06日06:29]
  • 300元以下,难购真羽绒服?
  • [2025年11月06日06:31]
  • 人生的"午后时光"该怎样度过
  • [2025年11月06日06:30] + + + + + + + +
    + + + + + +
    + + + + +
    +
    + + + + +
    +
    +
    + + + + + + +
     人民网首页往日回顾
    + + + + +
    +
    +
    + +
     
    +
    +
    + + + + + diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/MAIN1762414599322VT345OU6TG.jpg b/schoolNewsCrawler/crawler/首页头条--人民网_files/MAIN1762414599322VT345OU6TG.jpg new file mode 100644 index 0000000..6178a3f Binary files /dev/null and b/schoolNewsCrawler/crawler/首页头条--人民网_files/MAIN1762414599322VT345OU6TG.jpg differ diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/common.js.下载 b/schoolNewsCrawler/crawler/首页头条--人民网_files/common.js.下载 new file mode 100644 index 0000000..ca6624d --- /dev/null +++ b/schoolNewsCrawler/crawler/首页头条--人民网_files/common.js.下载 @@ -0,0 +1 @@ +var _wdVersion=_wdVersion||{};_wdVersion.WD=_wdVersion.WD||"0",_wdVersion.CN="1";var _wdTimeOut=1800,_wdRUTimeout=30,_wdPerfTimeOut=60,_wdED="expires=Fri, 1 Jan 2038 00:00:00 GMT;",_wdCK="0",_wdJE="0",_wdHP="0",_wdFl=0,_wdTZ=0,_wdLG="",_wdCT="",_wdFS=0,_wdErr="1",_wdGidT=0,_wdDT=document.title==""?location.href:document.title,_wdCS,_wdSL=window.location.href,_wdHost=window.location.host,_wdRDM="",_wdRP=document.referrer,_wdUA=navigator.appName+" "+navigator.appVersion,_wdRUA=navigator.userAgent,_wdWS=window.screen,_wdBV=navigator.appVersion.substring(0,1),_wdNN=_wdUA.indexOf("Netscape")!=-1,_wdMC=_wdUA.indexOf("Mac")!=-1,_wdIE=_wdUA.indexOf("MSIE")!=-1,_wdOP=_wdRUA.indexOf("Opera")!=-1,_wdIEV=0,_wdCID,_wdBCID="0",_wdLS=0,_wdTO="1",_wdSID="",_wdDU=10,curtime=new Date,Aimg;String.prototype.trim=function(){var e=/^\s+|\s+$/g;return function(){return this.replace(e,"")}}();var _webdigObj=_webdigObj||{};_webdigObj.getMeta=function(e){var t=document.getElementsByTagName("meta");if(t){for(var w=0;w-1?"https:":"http:",_wdCA=_wdLP+_wecl;function println(e){}function _wdEC(){}window.onerror=_wdEC;function fesc(e){return e=new String(e),escape(e)}function wdhex(e){for(var t="",w,u=7;u>=0;u--)w=e>>>u*4&15,t+=w.toString(16);return t}function wdHash(e){if(!e||e=="")return 1;for(var t=1732584193,w=4023233417,u=0;u>>26)+(t<<16|w>>>16)-t,w=g+(w<<6)-w+(w<<16)&4294967295}return wdhex(t&2147483647)+wdhex(w)}function wdGenCID(){return wdHash(document.location+document.cookie+document.referrer+curtime.getTime())}function getCookie(e){var t=null,w=document.cookie,u=w.indexOf(e);return u!=-1&&(u+=e.length+1,e=w.indexOf(";",u),e==-1&&(e=w.length),t=w.substring(u,e)),t}function wdFlash(){var a="",b=navigator;if(b.plugins&&b.plugins.length){for(var c=0;c=2;c--)try{var d=eval("new ActiveXObject('ShockwaveFlash.ShockwaveFlash."+c+"');");if(d){a=c+".0";break}}catch(e){}return a}function send_ref(e,t){var w=!1,u=function(){w||(w=!0,typeof t=="function"&&t())};e=_wdCA+e,Aimg=new Image,Aimg.onload=function(){u(),_wdGidT=Aimg.height,Aimg.height==1&&_wd_ruid(_wdDU)},Aimg.onerror=u,Aimg.src=e}function send_bc(e){navigator.sendBeacon?(e=_wdCA+e,navigator.sendBeacon(e)):send_ref(e)}function wd_tracker(e){if(setup_data({}),e&&e!=""){var t=_wdSL;e.toLowerCase().indexOf("http")!=0&&(e=_wdLP+"//"+_wdHost+e),_wdSL=e,_wdRP=t}write_ref()}function wd_reptracker(e,t){setup_data({}),e&&e!=""&&(_wdSL=_wdLP+"//"+_wdHost+e),write_ref()}function getmetaContents(e){var t=document.getElementsByTagName("meta");for(var w in t)if(t[w].name==e)return t[w].content}function setup_metadata(e){_webdigObj.catalogs=e.wdc||_webdigObj.getMeta("catalogs")||_webdigObj.catalogs,_webdigObj.contentid=e.wdci||_webdigObj.getMeta("contentid"),_webdigObj.filetype=_webdigObj.getMeta("filetype"),_webdigObj.pagetype=_webdigObj.getMeta("pagetype"),_webdigObj.publishedtype=_webdigObj.getMeta("publishedtype"),_webdigObj.publishdate=_webdigObj.getMeta("publishdate"),_webdigObj.author=_webdigObj.getMeta("author"),_webdigObj.editor=_webdigObj.getMeta("editor"),_webdigObj.reporter=_webdigObj.getMeta("reporter"),_webdigObj.subject=_webdigObj.getMeta("subject"),_webdigObj.source=_webdigObj.source||_webdigObj.getMeta("source"),_webdigObj.sourcetype=_webdigObj.getMeta("sourcetype"),_webdigObj.pageversion=_webdigObj.getMeta("pageversion"),_webdigObj.partner=_webdigObj.getMeta("partner"),_webdigObj.speical=_webdigObj.getMeta("webterren_speical"),_webdigObj.dept=_webdigObj.getMeta("dept"),_webdigObj.sec=_webdigObj.pro||function(){},_webdigObj.sec(),_webdigObj.url=function(){var t="";return t="_wdc="+escape(_webdigObj.catalogs)+"&",_webdigObj.subject&&(t+="_wds="+escape(_webdigObj.subject)+"&"),t+="_wdt="+escape(_webdigObj.filetype?_webdigObj.filetype:0)+escape(_webdigObj.publishedtype?_webdigObj.publishedtype:0)+escape(_webdigObj.pagetype?_webdigObj.pagetype:0)+"&",_webdigObj.contentid?e.sub_page_id?t+="_wdci="+escape(_webdigObj.contentid+"-"+e.sub_page_id)+"&":t+="_wdci="+escape(_webdigObj.contentid)+"&":e.sub_page_id&&(t+="_wdci="+escape(e.sub_page_id)+"&"),_webdigObj.publishdate&&(t+="_wdp="+escape(_webdigObj.publishdate)+"&"),_webdigObj.author&&(t+="_wda="+escape(_webdigObj.author)+"&",t+="_wdmd="+escape(_webdigObj.author)+"&"),_webdigObj.editor&&(t+="_wda2="+escape(_webdigObj.editor)+"&"),_webdigObj.reporter&&(t+="_wdr="+escape(_webdigObj.reporter)+"&"),_webdigObj.source&&(t+="_wdori="+escape(_webdigObj.source)+"&"),_webdigObj.sourcetype&&(t+="_wdot="+escape(_webdigObj.sourcetype)+"&"),_webdigObj.speical&&(t+="_wdsp="+escape(_webdigObj.speical)+"&"),_webdigObj.pageversion&&(t+="_wdvs="+escape(_webdigObj.pageversion)+"&"),_webdigObj.partner&&(t+="_wdqd="+escape(_webdigObj.partner)+"&"),_webdigObj.dept&&(t+="_wddp="+escape(_webdigObj.dept)+"&"),t}()}function _wd_write_ref(e,t,w){typeof t=="undefined"&&(t={}),curtime=new Date,setup_data(t),setup_metadata(t);var u="";for(k in t)typeof k=="string"&&k.startsWith("wd")||(u+=encodeURIComponent(k)+"="+encodeURIComponent(t[k])+"&");e=u+e,_webdigObj.url&&(e+="&"+_webdigObj.url),_wdSL=_wdSL.indexOf("?")==-1?_wdSL+"?"+e:_wdSL+"&"+e,write_ref(w)}function _wd_paramtracker(e,t){typeof e=="object"?_wd_write_ref("_wdxid=000000000000000000000000000000000000000000",e,t):_wd_write_ref(e,{},t)}function _wd_write_perf(e,t){var w,u,g;if(e){let v=function(h){return m>t.to*1e3?-1:h>0&&h=3&&s[1]=="c"&&(s[2]=="s"?(s=s.splice(2,s.length),s[0]="https:/"):(s=s.splice(1,s.length),s[0]="http:/"),_wdSL=s.join("/")+u+g,_wdHost=s[1])}if(document.location.protocol!="file:"){if(document.characterSet?_wdCS=fesc(document.characterSet):document.charset&&(_wdCS=fesc(document.charset)),INCLUDESUBHOST&&INCLUDESUBHOST!=null&&INCLUDESUBHOST.length!=0){for(i=0;i=0&&r<=8||_wdRP.indexOf("[")==0&&_wdRP.lastIndexOf("]")==_wdRP.length-1&&(_wdRP="")),println("_wdRP="+_wdRP),println("_wdUA="+_wdUA),println("_wdRUA="+_wdRUA),_wdIE&&(_wdIEV=parseInt(_wdUA.substr(_wdUA.indexOf("MSIE")+5))),_wdIE&&_wdIEV>=5&&(document.body.addBehavior("#default#clientCaps"),_wdCT=document.body.connectionType,document.body.addBehavior("#default#homePage"),_wdHP=document.body.isHomePage(location.href)?"1":"0");try{_wdIE&&(_wdFS=document.fileSize)}catch(m){_wdFS=0}_wdFl=wdFlash(),_wdTZ=new Date().getTimezoneOffset()/-60,typeof _wdWS!="undefined"&&_wdWS!=null&&(_wdSW=_wdWS.width,_wdSH=_wdWS.height,_wdCD=_wdWS.colorDepth,_wdSR=_wdSW+"x"+_wdSH,_wdNN&&_wdBV>=4&&(_wdCD=_wdWS.pixelDepth)),(_wdNN&&_wdBV>=4||_wdOP)&&(_wdLG=navigator.language),_wdIE&&_wdBV>=4&&!_wdOP&&(_wdLG=navigator.userLanguage),_wdJE=navigator.javaEnabled()==!0?"1":"0",navigator.cookieEnabled&&(_wdCK=navigator.cookieEnabled==!0?"1":"0"),_wdCK==1&&setup_cookie()}}}function _wd_ruid(e){var t=1;if(self==top&&e>_wdRUTimeout){for(var w="",u=navigator.userAgent,g=0,s=0;s=64)break}var O=Math.random().toString(36).substring(2),y="r-"+wdHash(w)+"-"+O+"-"+t+"-"+e,v=_wdCA.replace("1.gif",y),j=new Image;j.src=v}}function setup_cookie(){var e=document.cookie,t=e.indexOf("wdcid=");if(t<0){if(_wdBCID="0",_wdCID=wdGenCID(),t="",_wdRDM&&_wdRDM!=""&&(t="domain="+_wdRDM+";"),document.cookie="wdcid="+escape(_wdCID)+";"+_wdED+t+"path=/;",document.cookie.indexOf("wdcid=")<0){_wdCK=0;return}}else _wdBCID="1",_wdCID=getCookie("wdcid");t=document.cookie.indexOf("wdlast="),t<0?_wdLS=0:(_wdLS=parseInt(getCookie("wdlast")),_wdDU=Math.round(curtime.getTime()/1e3-_wdLS),_wdDU<=_wdTimeOut&&(_wdTO="0")),document.cookie="wdlast="+Math.round(curtime.getTime()/1e3)+";"+_wdED+"path=/;",t=document.cookie.indexOf("wdses="),t<0||_wdTO=="1"?(_wdTO="1",_wdSID=wdGenCID(),_wdDU=10,document.cookie="wdses="+_wdSID+";path=/;"):_wdSID=getCookie("wdses")}function write_ref(e){_wdCK=="0"?_dgURL=getGeneralInfo()+getLocalInfo():_dgURL=getGeneralInfo()+getCookieInfo()+getLocalInfo(),send_ref(_dgURL,e)}function write_bc(){_wdCK=="0"?_dgURL=getGeneralInfo()+getLocalInfo():_dgURL=getGeneralInfo()+getCookieInfo()+getLocalInfo(),send_bc(_dgURL)}function getGeneralInfo(){var e=_wdVersion.WD+"-"+_wdVersion.CN;return"?z="+_wdUID+"&a="+curtime.getTime().toString(16)+"&b="+fesc(_wdDT)+"&B="+_wdCS+"&c="+fesc(_wdSL)+"&d="+fesc(_wdRP)+"&e="+_wdDU+"&f="+_wdSID+"&H="+fesc(_wdHost)+"&E="+_wdErr+"&V="+e}function getLocalInfo(){return"&i="+fesc(_wdLG)+"&j="+_wdJE+"&k="+_wdSR+"&l="+_wdCD+"&m="+_wdFl+"&n="+fesc(_wdCT)+"&o="+_wdTZ}function getCookieInfo(){return"&r="+_wdCID+"&s="+_wdBCID+"&t="+_wdLS+"&u="+_wdTO}(function(){if(window._wd_common_loaded)return;window._wd_common_loaded=new Date;function e(n){switch(n[0]){case"wd_paramtracker":_wd_paramtracker(n[1],n[2]);break;case"wd_track_inner_page":var o=Array.prototype.slice.call(n,1);_wd_track_inner_page.apply(null,o);break;case"wd_track_user":var o=Array.prototype.slice.call(n,1);_wd_track_user.apply(null,o);break;case"wd_track_perf":var o=Array.prototype.slice.call(n,1);_wd_track_perf.apply(null,o);break;default:}}if(typeof _wd_o!="undefined"){let n=function(){window[_wd_o].q=window[_wd_o].q||[];for(var o=window[_wd_o].q,_=0;_10?D():t.push(_)}function C(n){for(var o="",_=0;_0){var n=C(t.splice(0,t.length));s(n)}}function h(){if(!!g("uctk")){var n=T("iframe"),o=function(f){return function(l){j(l,f)}};if(window.addEventListener){document.addEventListener("click",function(f){j(f)},!0),window.addEventListener("unload",function(f){D()},!0);for(var _=0;_0&&o[0]=="."&&n==o.substring(1))return!0}return!1}function I(n,o){if(!(!n||!n.hostname||n.href.indexOf("http")!=0)&&!(!o&&L(n.hostname))){var _=n.getAttribute("eltkstat");_||(n.addEventListener?(n.addEventListener("click",function(f){var l=f.currentTarget,p={url:l.href,referer:document.location.href,title:l.textContent};_wd_track_external(p)}),n.setAttribute("eltkstat",!0)):n.attachEvent&&(n.attachEvent("onclick",function(){var f=window.event.srcElement,l={url:f.href,referer:document.location.href,title:f.innerText};_wd_track_external(l)}),n.setAttribute("eltkstat",!0)))}}function R(){for(var n=g("eltk"),o=document.getElementsByTagName("a"),_=0;_ + + 人民网 + + + + + + +
    + + + + + +
    + + + + + +
    + +
    + + + + + + + + + + + +
    + + +
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
    +
    +
    + + + + \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/saved_resource.html b/schoolNewsCrawler/crawler/首页头条--人民网_files/saved_resource.html new file mode 100644 index 0000000..08f5e76 --- /dev/null +++ b/schoolNewsCrawler/crawler/首页头条--人民网_files/saved_resource.html @@ -0,0 +1,162 @@ + + + + 人民网 + + + + + + +
    + + + + + +
    + + + + + +
    + +
    + + + + + + + + + + + +
    + + +
          1
    2345678
    9101112131415
    16171819202122
    23242526272829
    30      
    +
    +
    + + + + \ No newline at end of file diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/top_01.jpg b/schoolNewsCrawler/crawler/首页头条--人民网_files/top_01.jpg new file mode 100644 index 0000000..ea344be Binary files /dev/null and b/schoolNewsCrawler/crawler/首页头条--人民网_files/top_01.jpg differ diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/top_02.jpg b/schoolNewsCrawler/crawler/首页头条--人民网_files/top_02.jpg new file mode 100644 index 0000000..e397d78 Binary files /dev/null and b/schoolNewsCrawler/crawler/首页头条--人民网_files/top_02.jpg differ diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/top_03.jpg b/schoolNewsCrawler/crawler/首页头条--人民网_files/top_03.jpg new file mode 100644 index 0000000..74f1c36 Binary files /dev/null and b/schoolNewsCrawler/crawler/首页头条--人民网_files/top_03.jpg differ diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/webdig.js.下载 b/schoolNewsCrawler/crawler/首页头条--人民网_files/webdig.js.下载 new file mode 100644 index 0000000..d83dd1d --- /dev/null +++ b/schoolNewsCrawler/crawler/首页头条--人民网_files/webdig.js.下载 @@ -0,0 +1 @@ +var ROOTDM=[".haiwainet.cn",".0898.net",".cpcnews.cn",".linliwang.com",".npopss-cn.gov.cn",".osports.com.cn",".people.cn",".people.com.cn",".people.gkcx.eol.cn",".people.nihaowang.com",".peopledaily.com.cn",".urbanchina.org",".zgdsw.org.cn",".zhengwutong.com",".zzdjw.org.cn",".cpta.com.cn",".chinawriter.com.cn",".djyj.cn",".nanhaimuseum.org",".womenvoice.cn",".womencn.cn",".rmxiongan.com",".zghrg.gov.cn",".gjbmj.gov.cn",".chinaql.org",".minge.gov.cn",".chinaxiongan.cn",".qizhiwang.org.cn",".brnn.com",".dswxyjy.org.cn",".chinalianxun.cn",".cidf.net",".fpzg.cpad.gov.cn",".nopss.gov.cn",".hlj.gov.cn",".lmcchina.org",".peopletech.cn",".miguvideo.com",".zyshgzb.gov.cn",".12380.gov.cn",".sxdaily.com.cn"],RECENDM=[],INCLUDESUBHOST=["www.people.com.cn"],SHOWERRHOST=1,_wdUID="15",_wecl="//cl0.webterren.com/1.gif",_wdVersion={WD:1726819015},_wevcl="//cl0.webterren.com/2.gif";function _wd_re(n,o){var c=document;if(n.length==0){typeof o=="function"&&o();return}function a(){_wd_re(n,o)}var t=n.splice(0,1),e=c.createElement("script");e.type="text/javascript",e.referrerPolicy="no-referrer-when-downgrade";function r(){(e.readyState=="loaded"||e.readyState=="complete")&&(e.onreadystatechange=null,a())}e.readyState?e.onreadystatechange=r:e.onload=a,e.src=t,c.getElementsByTagName("head")[0].appendChild(e)}var _wd_ss=["//d.webterren.com/common.js?z=15&t=202409200756"];window._wd_o?function(){var n,o="_wd_load_event",c=document,a=!!c.createEvent;a?(n=c.createEvent("Event"),n.initEvent(o,!0,!0)):(n=c.createElement("p"),c.body.appendChild(n)),window[_wd_o].e=n,_wd_re(_wd_ss,function(){a?c.dispatchEvent(n):n[o]=new Date})}():window.wd_paramtracker=function(){var n=arguments[0];_wd_re(_wd_ss,function(){_wd_paramtracker(n)})}; diff --git a/schoolNewsCrawler/crawler/首页头条--人民网_files/webdig_test.js.下载 b/schoolNewsCrawler/crawler/首页头条--人民网_files/webdig_test.js.下载 new file mode 100644 index 0000000..785cb97 --- /dev/null +++ b/schoolNewsCrawler/crawler/首页头条--人民网_files/webdig_test.js.下载 @@ -0,0 +1,8 @@ +(function(w,d,g,r){ + w['_wd_o']=r; + w[r]=w[r]||function(){arguments.t=1*new Date(),(w[r].q=w[r].q||[]).push(arguments);}; + var a=d.createElement('script'),m=d.getElementsByTagName('script')[0]; + a.async=1;a.src=g;m.parentNode.insertBefore(a,m); +})(window,document,'//cl2.webterren.com/webdig.js?z=15','_wa'); + +_wa('wd_paramtracker', '_wdxid=000000000000000000000000000000000000000000'); diff --git a/schoolNewsCrawler/main.py b/schoolNewsCrawler/main.py new file mode 100644 index 0000000..dc9103f --- /dev/null +++ b/schoolNewsCrawler/main.py @@ -0,0 +1,123 @@ +""" +新闻爬虫主程序 +用于被定时任务调用或独立运行 +""" + +import sys +import json +from typing import List +from loguru import logger +from crawler.RmrbCrawler import RmrbCrawler +from crawler.BaseCrawler import NewsItem + + +# 配置日志 +logger.remove() # 移除默认处理器 +logger.add( + sys.stdout, + format="{time:YYYY-MM-DD HH:mm:ss} | {level: <8} | {name}:{function} - {message}", + level="INFO" +) +logger.add( + "logs/crawler_{time:YYYY-MM-DD}.log", + rotation="00:00", + retention="30 days", + encoding="utf-8", + level="DEBUG" +) + + +def crawl_rmrb_news(category: str = "politics", limit: int = 20) -> List[dict]: + """ + 爬取人民日报新闻 + + Args: + category: 新闻分类 + limit: 爬取数量 + + Returns: + 新闻列表(字典格式) + """ + logger.info(f"开始爬取人民日报新闻 - 分类: {category}, 数量: {limit}") + + crawler = None + try: + crawler = RmrbCrawler() + news_list = crawler.crawl(category=category, limit=limit) + + # 转换为字典列表 + result = [news.model_dump() for news in news_list] + + logger.info(f"爬取完成,共获取 {len(result)} 条新闻") + return result + + except Exception as e: + logger.error(f"爬取失败: {str(e)}") + return [] + + finally: + if crawler: + crawler.close() + + +def save_to_json(news_list: List[dict], output_file: str = "output/news.json"): + """ + 保存新闻到JSON文件 + + Args: + news_list: 新闻列表 + output_file: 输出文件路径 + """ + try: + import os + os.makedirs(os.path.dirname(output_file), exist_ok=True) + + with open(output_file, 'w', encoding='utf-8') as f: + json.dump(news_list, f, ensure_ascii=False, indent=2) + + logger.info(f"新闻已保存到: {output_file}") + + except Exception as e: + logger.error(f"保存文件失败: {str(e)}") + + +def main(): + """主函数""" + # 解析命令行参数 + category = "politics" + limit = 20 + output_file = "output/news.json" + + if len(sys.argv) > 1: + category = sys.argv[1] + if len(sys.argv) > 2: + limit = int(sys.argv[2]) + if len(sys.argv) > 3: + output_file = sys.argv[3] + + logger.info("=" * 60) + logger.info("新闻爬虫程序启动") + logger.info("=" * 60) + + # 爬取新闻 + news_list = crawl_rmrb_news(category=category, limit=limit) + + # 保存结果 + if news_list: + save_to_json(news_list, output_file) + + # 输出统计信息 + logger.info(f"爬取统计:") + logger.info(f" - 成功: {len(news_list)} 条") + logger.info(f" - 失败: {limit - len(news_list)} 条") + else: + logger.warning("未获取到任何新闻") + + logger.info("=" * 60) + logger.info("新闻爬虫程序结束") + logger.info("=" * 60) + + +if __name__ == "__main__": + main() + diff --git a/schoolNewsCrawler/requirements.txt b/schoolNewsCrawler/requirements.txt new file mode 100644 index 0000000..4ef7109 --- /dev/null +++ b/schoolNewsCrawler/requirements.txt @@ -0,0 +1,77 @@ +# 核心爬虫库 +requests # HTTP请求库 +beautifulsoup4 # HTML/XML解析库 +lxml # 高性能HTML/XML解析器 +selenium # 浏览器自动化(用于动态页面) +scrapy # 专业爬虫框架(可选) +crawl4ai # 基于 Playwright 的智能爬虫框架 +playwright # 浏览器自动化框架(Crawl4AI 依赖) + +# 异步支持 +aiohttp # 异步HTTP客户端 +asyncio # 异步IO支持 +httpx # 现代HTTP客户端,支持异步 + +# 数据校验与类型检查 +pydantic # 数据验证和设置管理 +pydantic-settings # Pydantic配置管理 +typing-extensions # 类型注解扩展 +mypy # 静态类型检查器 + +# 数据处理 +pandas # 数据分析和处理 +openpyxl # Excel文件读写 +python-dateutil # 日期时间处理 +pytz # 时区处理 + +# 日志与调试 +loguru # 现代化日志库 +colorlog # 彩色日志输出 + +# 配置管理 +python-dotenv # 环境变量管理 +pyyaml # YAML配置文件支持 + +# 数据库连接(用于存储爬取的数据) +pymysql # MySQL数据库连接 +sqlalchemy # ORM框架 + +# HTTP客户端增强 +urllib3 # HTTP库 +certifi # SSL证书 +charset-normalizer # 字符编码检测 + +# HTML处理增强 +html5lib # HTML5解析器 +cssselect # CSS选择器 + +# 反爬虫对策 +fake-useragent # 随机User-Agent +pyquery # jQuery风格的HTML解析 + +# 图片处理(如果需要下载图片) +Pillow # 图像处理库 + +# 网络工具 +chardet # 字符编码检测 + +# 定时任务(如果Python端需要独立运行) +schedule # 简单的定时任务库 +apscheduler # 高级定时任务调度器 + +# WebDriver管理(自动下载浏览器驱动) +webdriver-manager # 自动管理Selenium WebDriver + +# JSON处理增强 +jsonschema # JSON数据验证 + +# 代理支持 +pysocks # SOCKS代理支持 + +# 开发工具 +pytest # 测试框架 +pytest-asyncio # 异步测试支持 +black # 代码格式化 +flake8 # 代码风格检查 +isort # import排序 +