news 2026/7/10 11:19:35

东方财富股吧爬虫实战:Selenium + MongoDB 存储 5000+ 条数据的完整流程

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
东方财富股吧爬虫实战:Selenium + MongoDB 存储 5000+ 条数据的完整流程

东方财富股吧数据采集实战:基于Selenium与MongoDB的高效爬虫架构设计

在金融数据分析领域,东方财富股吧作为国内活跃的股票讨论社区,蕴含着大量有价值的市场情绪数据。本文将深入讲解如何构建一个高效、稳定的数据采集系统,通过Selenium模拟真实用户操作获取动态渲染内容,并利用MongoDB实现非结构化数据的灵活存储。不同于简单的代码示例,我们将从工程化角度剖析爬虫系统的核心设计要点。

1. 环境配置与工具选型

1.1 技术栈对比分析

在选择爬虫技术方案时,我们需要考虑目标网站的技术特点和采集需求:

技术方案适用场景优缺点对比
静态页面采集传统HTML页面速度快但无法处理动态内容
SeleniumJavaScript渲染的动态页面真实模拟但资源消耗较大
Playwright复杂交互场景性能更优但生态较新

对于东方财富股吧这类高度依赖JavaScript渲染的SPA应用,Selenium仍然是目前最可靠的选择。其优势在于:

  • 完整模拟浏览器环境
  • 支持所有现代Web技术
  • 丰富的元素定位方式
  • 成熟的异常处理机制

1.2 环境准备清单

完整的开发环境需要以下组件:

# Python基础环境 python==3.8+ pip install selenium==4.0.0 pip install pymongo==4.0.1 pip install webdriver-manager==3.8.3 # 数据库环境 mongodb-community==5.0+

提示:建议使用conda创建独立的Python环境,避免包版本冲突。Webdriver-manager可自动管理浏览器驱动版本,减少环境配置问题。

1.3 浏览器驱动配置技巧

Chromedriver的配置直接影响爬虫的稳定性和隐蔽性:

from selenium import webdriver from selenium.webdriver.chrome.service import Service from webdriver_manager.chrome import ChromeDriverManager chrome_options = webdriver.ChromeOptions() chrome_options.add_argument('--disable-blink-features=AutomationControlled') chrome_options.add_argument('--disable-infobars') chrome_options.add_argument('--start-maximized') service = Service(ChromeDriverManager().install()) driver = webdriver.Chrome(service=service, options=chrome_options)

关键配置参数说明:

  • disable-automation:隐藏自动化测试标志
  • disable-infobars:移除Chrome提示栏
  • start-maximized:以最大化窗口运行,避免响应式布局问题

2. 爬虫架构设计与实现

2.1 模块化工程结构

专业级爬虫项目应采用分层架构:

eastmoney_crawler/ ├── core/ │ ├── crawler.py # 核心爬取逻辑 │ ├── parser.py # 页面解析器 │ └── storage.py # 数据存储接口 ├── utils/ │ ├── logger.py # 日志记录 │ └── proxy.py # 代理管理 ├── config/ │ └── settings.py # 全局配置 └── main.py # 入口程序

2.2 多线程优化方案

针对股吧分页特性,我们设计多线程采集方案:

import threading from queue import Queue class ThreadPool: def __init__(self, thread_num=5): self.work_queue = Queue() self.threads = [] self._init_threads(thread_num) def _init_threads(self, thread_num): for _ in range(thread_num): thread = CrawlerThread(self.work_queue) thread.daemon = True thread.start() self.threads.append(thread) def add_task(self, func, *args): self.work_queue.put((func, args)) class CrawlerThread(threading.Thread): def __init__(self, work_queue): super().__init__() self.work_queue = work_queue def run(self): while True: func, args = self.work_queue.get() try: func(*args) except Exception as e: print(f"Thread error: {e}") finally: self.work_queue.task_done()

关键设计要点:

  • 使用生产者-消费者模式避免资源竞争
  • 守护线程确保程序可正常退出
  • 异常捕获防止单个线程崩溃影响整体

2.3 反反爬策略集成

针对东方财富的反爬机制,我们需要实现多重防护:

  1. 请求频率控制
import random import time def random_delay(min=2, max=5): time.sleep(random.uniform(min, max))
  1. User-Agent轮换
from fake_useragent import UserAgent def get_random_ua(): return UserAgent().chrome
  1. 行为模式模拟
from selenium.webdriver.common.action_chains import ActionChains def human_like_behavior(driver): # 模拟鼠标移动轨迹 actions = ActionChains(driver) for _ in range(3): x_offset = random.randint(-50, 50) y_offset = random.randint(-50, 50) actions.move_by_offset(x_offset, y_offset) actions.perform()

3. MongoDB数据建模与优化

3.1 文档结构设计

针对股吧数据特点,我们设计以下文档结构:

post_schema = { 'post_id': 'str', # 帖子唯一标识 'stock_code': 'str', # 关联股票代码 'title': 'str', # 帖子标题 'content': 'str', # 正文内容 'view_count': 'int', # 浏览数 'comment_count': 'int', # 评论数 'publish_time': 'datetime', # 发布时间 'author': 'str', # 发帖人 'sentiment': 'float' # 情感分析值 } comment_schema = { 'comment_id': 'str', # 评论唯一标识 'post_id': 'str', # 关联帖子ID 'content': 'str', # 评论内容 'like_count': 'int', # 点赞数 'publish_time': 'datetime', # 发布时间 'user_level': 'str' # 用户等级 }

3.2 索引优化策略

合理的索引设计能显著提升查询性能:

# 帖子集合索引 db.post_info.create_index([('post_id', pymongo.ASCENDING)], unique=True) db.post_info.create_index([('stock_code', pymongo.ASCENDING)]) db.post_info.create_index([('publish_time', pymongo.DESCENDING)]) # 评论集合索引 db.comment_info.create_index([('comment_id', pymongo.ASCENDING)], unique=True) db.comment_info.create_index([('post_id', pymongo.ASCENDING)])

3.3 批量写入优化

使用bulk_write替代单条插入提升IO效率:

from pymongo import InsertOne def batch_insert(collection, data_list): operations = [InsertOne(data) for data in data_list] result = collection.bulk_write(operations) return result.inserted_count

4. 实战:完整爬取流程解析

4.1 帖子列表采集

分页采集的核心逻辑实现:

def crawl_posts(driver, stock_code, start_page=1, end_page=10): base_url = f"http://guba.eastmoney.com/list,{stock_code}" post_list = [] for page in range(start_page, end_page + 1): try: url = f"{base_url}_{page}.html" driver.get(url) WebDriverWait(driver, 10).until( EC.presence_of_element_located((By.CSS_SELECTOR, ".articleh")) ) # 解析帖子列表 posts = driver.find_elements(By.CSS_SELECTOR, ".articleh") for post in posts: post_data = parse_post(post) post_list.append(post_data) random_delay() except Exception as e: print(f"Page {page} error: {str(e)}") continue return post_list

4.2 评论数据采集

动态加载评论的处理方法:

def crawl_comments(driver, post_url): driver.get(post_url) comment_list = [] try: # 点击"查看更多评论" while True: more_btn = driver.find_element(By.CSS_SELECTOR, ".more_comment") if "hide" in more_btn.get_attribute("class"): break driver.execute_script("arguments[0].click();", more_btn) time.sleep(1) # 解析评论内容 comments = driver.find_elements(By.CSS_SELECTOR, ".comment_item") for comment in comments: comment_data = parse_comment(comment) comment_list.append(comment_data) except Exception as e: print(f"Comment crawl error: {str(e)}") return comment_list

4.3 断点续采实现

确保采集任务可恢复的关键机制:

def get_checkpoint(stock_code): """获取上次采集的断点位置""" checkpoint = db.checkpoints.find_one({"stock_code": stock_code}) return checkpoint["last_page"] if checkpoint else 1 def save_checkpoint(stock_code, page): """保存当前采集进度""" db.checkpoints.update_one( {"stock_code": stock_code}, {"$set": {"last_page": page}}, upsert=True )

5. 性能监控与异常处理

5.1 健康检查体系

class HealthMonitor: def __init__(self): self.start_time = time.time() self.success_count = 0 self.error_count = 0 def record_success(self): self.success_count += 1 def record_error(self): self.error_count += 1 def get_stats(self): duration = time.time() - self.start_time return { "duration": round(duration, 2), "success_rate": self.success_count / (self.success_count + self.error_count), "req_per_second": self.success_count / duration }

5.2 常见异常处理方案

异常类型触发场景处理策略
TimeoutException页面加载超时重试机制+代理切换
NoSuchElementException元素定位失败备用选择器+日志记录
StaleElementReferenceDOM结构变化元素重新定位
ProxyError代理不可用自动切换备用代理

5.3 日志系统集成

专业级的日志记录配置:

import logging from logging.handlers import RotatingFileHandler def init_logger(name): logger = logging.getLogger(name) logger.setLevel(logging.INFO) formatter = logging.Formatter( '%(asctime)s - %(name)s - %(levelname)s - %(message)s' ) # 控制台输出 console_handler = logging.StreamHandler() console_handler.setFormatter(formatter) # 文件输出(自动轮转) file_handler = RotatingFileHandler( 'crawler.log', maxBytes=10*1024*1024, backupCount=5 ) file_handler.setFormatter(formatter) logger.addHandler(console_handler) logger.addHandler(file_handler) return logger

在实际项目中,我们还需要考虑分布式部署、定时任务调度、数据质量监控等进阶话题。通过合理的架构设计和代码规范,可以构建出能够持续稳定运行的金融数据采集系统。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/7/10 11:14:25

腾讯、字节、阿里盯上“Work”,AI办公产品如何突破聊天框局限?

巨头布局“Work”领域腾讯、字节、阿里又盯上了“Work”。7月2日,据新浪科技报道,阿里巴巴正在对旗下Agent产品线进行系统性整合,以QoderWork为基础底座,融合“悟空”与“MuleRun(骡子快跑)”的核心能力&am…

作者头像 李华
网站建设 2026/7/10 11:05:46

终极指南:使用命令行快速上传大文件到 Zenodo 研究平台

终极指南:使用命令行快速上传大文件到 Zenodo 研究平台 【免费下载链接】zenodo-upload upload big files to Zenodo using cURL, jq and bash 项目地址: https://gitcode.com/gh_mirrors/ze/zenodo-upload 在科研和学术工作中,数据共享和研究成果…

作者头像 李华
网站建设 2026/7/10 11:02:31

Seaborn vs Matplotlib vs Plotly:3种工具绘制热力图性能与效果深度对比

Seaborn vs Matplotlib vs Plotly:热力图绘制工具全方位对比指南 1. 热力图工具选型的关键维度 当我们需要在Python中绘制热力图时,Seaborn、Matplotlib和Plotly是三个最常用的可视化库。这三种工具各有特点,适用于不同的场景需求。以下是五…

作者头像 李华
网站建设 2026/7/10 11:00:02

TB67H480FNG与dsPIC33EP512MU814在电机控制中的高效组合

1. 项目概述:TB67H480FNG与dsPIC33EP512MU814的黄金组合 在电机控制和嵌入式系统开发领域,选择合适的驱动芯片和微控制器往往是项目成败的关键。TB67H480FNG(东芝的步进电机驱动器)与dsPIC33EP512MU814(Microchip的高性…

作者头像 李华