102302149赖翊煊数据采集与融合技术第四次作业

news/2025/12/7 23:06:18/文章来源:https://www.cnblogs.com/laiyixuan/p/19309451

作业一

代码及其结果展示

点击查看代码
from selenium import webdriver
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.firefox.options import Options
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pymysql
import time
import re
import os
from datetime import datetime
import json# 1. 定义数值解析逻辑
def parse_value(text):if not text or text.strip() in ['-', '--', '']:return 0.00text = text.strip()if '万' in text:cleaned = re.sub(r'[^\d.-]', '', text)num = float(cleaned)return round(num / 10000, 4)elif '亿' in text:cleaned = re.sub(r'[^\d.-]', '', text)num = float(cleaned)return round(num, 4)elif '%' in text:cleaned = re.sub(r'[^\d.-]', '', text)num = float(cleaned)return round(num, 2)else:cleaned = re.sub(r'[^\d.-]', '', text)if cleaned:num = float(cleaned)return round(num / 10000, 4)else:return 0.00# 2. 初始化数据库
# 获取数据库连接
conn = pymysql.connect(host='localhost',port=3306,user='root',password='123456',database='stock_db',charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor
)
cursor = conn.cursor()# 创建股票信息表
cursor.execute("""
CREATE TABLE IF NOT EXISTS stock_info (id BIGINT AUTO_INCREMENT PRIMARY KEY,stock_code VARCHAR(20) NOT NULL,stock_name VARCHAR(100) NOT NULL,latest_price DECIMAL(20,6),price_change_rate DECIMAL(15,6),price_change_amount DECIMAL(20,6),volume DECIMAL(25,6),turnover DECIMAL(25,6),amplitude DECIMAL(15,6),highest_price DECIMAL(20,6),lowest_price DECIMAL(20,6),opening_price DECIMAL(20,6),previous_close DECIMAL(20,6),plate VARCHAR(50),crawl_time DATETIME DEFAULT CURRENT_TIMESTAMP,update_time DATETIME DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,UNIQUE KEY uk_stock_plate (stock_code, plate)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
""")# 创建日志表
cursor.execute("""
CREATE TABLE IF NOT EXISTS crawl_log (id INT AUTO_INCREMENT PRIMARY KEY,plate VARCHAR(50) NOT NULL,crawl_date DATETIME DEFAULT CURRENT_TIMESTAMP,data_count INT NOT NULL,status VARCHAR(20) DEFAULT 'success',error_msg TEXT
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
""")
conn.commit()
cursor.close()
conn.close()# 3. 配置Firefox浏览器
options = Options()
firefox_paths = [r'C:\Program Files\Mozilla Firefox\firefox.exe',r'C:\Program Files (x86)\Mozilla Firefox\firefox.exe'
]
for path in firefox_paths:if os.path.exists(path):options.binary_location = pathbreakoptions.add_argument("--start-maximized")driver_path = r'C:\Users\27387\PycharmProjects\PythonProject\.venv\Scripts\geckodriver.exe'
if not os.path.exists(driver_path):driver_path = './geckodriver.exe'driver = webdriver.Firefox(service=Service(driver_path),options=options
)
driver.set_page_load_timeout(60)# 4. 爬取各板块数据
plates = [{"url": "http://quote.eastmoney.com/center/gridlist.html#hs_a_board", "name": "沪深京A股"},{"url": "http://quote.eastmoney.com/center/gridlist.html#sh_a_board", "name": "上证A股"},{"url": "http://quote.eastmoney.com/center/gridlist.html#sz_a_board", "name": "深证A股"}
]for plate in plates:print(f"\n爬取【{plate['name']}】...")driver.get(plate["url"])time.sleep(8)# 提取股票数据stock_list = []WebDriverWait(driver, 20).until(EC.presence_of_element_located((By.XPATH, "//div[@class='quotetable']//table")))rows = driver.find_elements(By.XPATH, "//div[@class='quotetable']//table//tbody/tr")for row in rows:cols = row.find_elements(By.TAG_NAME, "td")col_texts = [col.text.strip() for col in cols if col.text.strip()]if len(col_texts) < 13:continuestock_info = {"stock_code": col_texts[1],"stock_name": col_texts[2],"latest_price": parse_value(col_texts[4]),"price_change_rate": parse_value(col_texts[5]),"price_change_amount": parse_value(col_texts[6]),"volume": parse_value(col_texts[7]),"turnover": parse_value(col_texts[8]),"amplitude": parse_value(col_texts[9]),"highest_price": parse_value(col_texts[10]),"lowest_price": parse_value(col_texts[11]),"opening_price": parse_value(col_texts[12]),"previous_close": parse_value(col_texts[13]),"plate": plate_name}if stock_info["stock_code"] and len(stock_info["stock_code"]) >= 6:stock_list.append(stock_info)# 保存数据到数据库(原save_stock_data_to_db函数内容)if stock_list:conn = pymysql.connect(host='localhost',port=3306,user='root',password='123456',database='stock_db',charset='utf8mb4',cursorclass=pymysql.cursors.DictCursor)cursor = conn.cursor()insert_sql = """INSERT INTO stock_info (stock_code, stock_name, latest_price, price_change_rate,price_change_amount, volume, turnover, amplitude,highest_price, lowest_price, opening_price, previous_close, plate) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)ON DUPLICATE KEY UPDATEstock_name = VALUES(stock_name),latest_price = VALUES(latest_price),price_change_rate = VALUES(price_change_rate),price_change_amount = VALUES(price_change_amount),volume = VALUES(volume),turnover = VALUES(turnover),amplitude = VALUES(amplitude),highest_price = VALUES(highest_price),lowest_price = VALUES(lowest_price),opening_price = VALUES(opening_price),previous_close = VALUES(previous_close),update_time = CURRENT_TIMESTAMP"""data_list = [(s['stock_code'], s['stock_name'], s['latest_price'], s['price_change_rate'],s['price_change_amount'], s['volume'], s['turnover'], s['amplitude'],s['highest_price'], s['lowest_price'], s['opening_price'], s['previous_close'], s['plate']) for s in stock_list]cursor.executemany(insert_sql, data_list)cursor.execute("INSERT INTO crawl_log (plate, data_count) VALUES (%s, %s)",(plate['name'], len(stock_list)))conn.commit()cursor.close()conn.close()print(f"成功爬取 {len(stock_data)} 条数据")else:print("未提取到任何数据")# 5. 关闭浏览器
driver.quit()
print("\n所有板块爬取完成!")

图片1

心得体会

Selenium 在处理 Ajax 动态加载的网页时展现出独特优势。相较于传统爬虫库,它能模拟浏览器渲染页面,解决了股票数据异步加载难以直接抓取的问题,而合理运用显式等待(WebDriverWait)则有效避免了元素未加载完成导致的定位失败,让我深刻体会到 “等待” 在动态网页爬取中的核心作用。
此次实践让我将理论知识落地,既掌握了 Selenium 处理动态页面的核心技巧,也理解了数据爬取到存储全流程的逻辑,更认识到编程实践中严谨和复盘的重要性,为后续处理更复杂的爬虫场景积累了宝贵经验。

作业二

代码及其结果展示

点击查看代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.firefox.service import Service
from selenium.webdriver.support.wait import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import time
import pymysqloptions = webdriver.FirefoxOptions()
# 反爬配置
options.set_preference("dom.webdriver.enabled", False)
options.add_argument('--disable-blink-features=AutomationControlled')
options.add_argument("--disable-blink-features=AutomationControlled")
options.add_argument('--no-sandbox')
# 指定geckodriver路径
service = Service(r"C:\Users\27387\PycharmProjects\PythonProject\.venv\Scripts\geckodriver.exe")
driver = webdriver.Firefox(service=service, options=options)
driver.maximize_window()# 数据库连接
db = pymysql.connect(host='127.0.0.1', user='root', password='123456', port=3306, database='mooc_db')
cursor = db.cursor()
cursor.execute('DROP TABLE IF EXISTS courseMessage')
sql = '''CREATE TABLE courseMessage(cCourse varchar(64),cCollege varchar(64),cTeacher varchar(16),cTeam varchar(256),cCount varchar(16),
cProcess varchar(32),cBrief varchar(2048))'''
cursor.execute(sql)def spiderOnePage():time.sleep(3)courses = driver.find_elements(By.XPATH, '//*[@id="channel-course-list"]/div/div/div[2]/div[1]/div')current_window_handle = driver.current_window_handlefor course in courses:cCourse = course.find_element(By.XPATH, './/h3').text  # 提取课程名称cCollege = course.find_element(By.XPATH, './/p[@class="_2lZi3"]').text  # 提取院校cTeacher = course.find_element(By.XPATH, './/div[@class="_1Zkj9"]').text  # 提取老师cCount = course.find_element(By.XPATH, './/div[@class="jvxcQ"]/span').text  # 提取学校人数cProcess = course.find_element(By.XPATH, './/div[@class="jvxcQ"]/div').text  # 提取课程进度course.click()Handles = driver.window_handlesif len(Handles) < 2:continuedriver.switch_to.window(Handles[1])time.sleep(3)# 提取课程详情cBrief = driver.find_element(By.XPATH, '//*[@id="j-rectxt2"]').text  # 先通过固定ID找简介if len(cBrief) == 0:cBriefs = driver.find_elements(By.XPATH, '//*[@id="content-section"]/div[4]/div//*')  # 获取简介区块下的所有子元素cBrief = ""for c in cBriefs:cBrief += c.textcBrief = cBrief.replace('"', r'\"').replace("'", r"\'")cBrief = cBrief.strip()nameList = []cTeachers = driver.find_elements(By.XPATH, '//div[@class="um-list-slider_con_item"]')  # 提取授课团队for Teacher in cTeachers:name = Teacher.find_element(By.XPATH, './/h3[@class="f-fc3"]').text.strip()nameList.append(name)nextButton = driver.find_elements(By.XPATH, '//div[@class="um-list-slider_next f-pa"]')  # 提取下一页按钮while len(nextButton) != 0:nextButton[0].click()time.sleep(3)cTeachers = driver.find_elements(By.XPATH, '//div[@class="um-list-slider_con_item"]')for Teacher in cTeachers:name = Teacher.find_element(By.XPATH, './/h3[@class="f-fc3"]').text.strip()nameList.append(name)nextButton = driver.find_elements(By.XPATH, '//div[@class="um-list-slider_next f-pa"]')cTeam = ','.join(nameList)# 关闭详情页driver.close()driver.switch_to.window(current_window_handle)# 插入数据库cursor.execute('INSERT INTO courseMessage VALUES ("%s","%s","%s","%s","%s","%s","%s")' % (cCourse, cCollege, cTeacher, cTeam, cCount, cProcess, cBrief))db.commit()driver.get('https://www.icourse163.org/')
driver.get(WebDriverWait(driver, 10, 0.48).until(EC.presence_of_element_located((By.XPATH, '//*[@id="app"]/div/div/div[1]/div[1]/div[1]/span[1]/a'))).get_attribute('href'))
spiderOnePage()
count = 1
# 翻页逻辑
next_page = driver.find_element(By.XPATH, '//*[@id="channel-course-list"]/div/div/div[2]/div[2]/div/a[10]')
while next_page.get_attribute('class') == '_3YiUU ':if count == 2:breakcount += 1next_page.click()spiderOnePage()next_page = driver.find_element(By.XPATH, '//*[@id="channel-course-list"]/div/div/div[2]/div[2]/div/a[10]')# 关闭数据库连接
cursor.close()
db.close()time.sleep(3)
driver.quit()

image

心得体会

在爬取过程中遇到爬取多个任课老师遗漏的问题,采取循环,每次都重新定位到成员卡片位置,直到找不到下一个数据为止,然后再用逗号拼接字符串。
image
image
在爬虫实现层面,我深刻体会到 Selenium 处理动态交互场景的优势:模拟用户点击课程卡片、切换浏览器窗口、点击团队成员翻页按钮等操作,完美解决了 Ajax 异步加载的课程简介、授课团队等数据无法直接抓取的问题;而显式等待的合理运用,有效规避了元素加载延迟导致的定位失败,让我意识到 “精准等待” 是提升爬虫稳定性的关键。同时,XPath 定位的细节处理(如相对路径、多场景适配课程简介提取),也让我掌握了动态页面元素定位的核心技巧。

作业三

Python脚本生成测试数据
image
Kafka配置成功
image
安装flume运行环境
image
测试flume,kafka通道
image
image

gitee链接:https://gitee.com/lai-yixuan/2025_crawl_project/tree/master/作业4

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/991882.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Homework

打开下载的文件,ctrl+f搜索flag,发现一部分flag将文件放进随波逐流里面,binwalk分离文件打开分离的网页,一个一个网页找在里面搜索}发现另一部分flag完整flag:moectf{0h_U_f1nd_m3!}

深入解析:【Rust 探索之旅】Rust 库开发实战教程:从零构建高性能 HTTP 客户端库

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

案例库--工抵协议系承包人主张优先受偿权的合法方式

案例库--工抵协议系承包人主张优先受偿权的合法方式2025-12-07 22:52 wwx的个人博客 阅读(0) 评论(0) 收藏 举报1. (2022)晋民再123号 海某建设公司诉丰某房地产开发公司建设工程施工合同纠纷案 裁判要旨:建设工…

251207周天,今天是周天

周末总体过得很快 现在的周末并不能给我很放松的感觉,反而是感觉周末过得很快。 今天上午去帮人练了球,中午吃了饭 下午感觉也没干啥,睡了一会儿。 晚上 才来工作,加油

完整教程:和AI用TDD结对编程:1天开发一个完整的 Python 库

完整教程:和AI用TDD结对编程:1天开发一个完整的 Python 库2025-12-07 22:46 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !importa…

如何保证 RocketMQ 消息不丢失

🚀 一句话总览:消息不丢 = 生产端不丢 + Broker 不丢 + 消费端不丢 你要牢牢记住:任何 MQ 最容易丢的不是 Broker,而是 Producer 和 Consumer。消息可靠性必须三段一起设计: Producer(发送) Broker(存储) …

排列组合

排列组合 加法原理 完成某件事情有 \(n\) 类方法,其中第 \(i\) 类方法有 \(a_i\) 种方案。 则总共有 \(\sum_{i=1}^na_i\) 种方案。 乘法原理 完成某件事有 \(n\) 个步骤,第 \(i\) 个步骤有 \(a_i\) 种方案。 则共有…

2025 最新西双版纳旅游服务商TOP5推荐!地接社/旅行社五大优质品牌,资源实力 + 服务口碑权威榜单发布,专业赋能构筑美好旅行体验

随着西双版纳成为国内外游客向往的热带旅游目的地,市场对优质旅行社的需求持续攀升。本榜单基于资源整合力、服务专业度、产品创新力、客户口碑四大维度,结合行业协会数据与游客真实反馈,权威解析2025年五大西双版纳…

12.4 maven简介

maven仓库分类 本地仓库:自己计算机上的一个目录 中央仓库:maven团队维护的全球唯一的一个仓库 远程仓库:公司团队自己搭建的仓库 自己本地有jar就用;无就下过来; alt+insert能快捷导入jar包 groupid artifactId …

vs2026远程调试linux

vs2026远程调试linux网上都搜索不到有关教程,自己摸索了一下。 vs2026的安装步骤直接跳过,创建项目时选择cmake的项目在Linux系统中,如果是使用yum的包管理(比如centos),下载一些软件,远程调试需要使用 sudo yu…

深入理解 RocketMQ 核心机制

🚀 一、RocketMQ 核心机制 = “日志 + 顺序写 + 消费位点 + 多副本 + 动态路由” 一句话:RocketMQ 是一个高性能、可扩展、牢靠不丢消息的分布式消息系统,本质是一套“持久化日志 + 分布式调度”的组合拳。 要理解…

DMY 周作业 47 简要题解

G 数据结构优化 DP 板。暑假的时候做过,直接离散化 + BIT 就行了。比较无聊就不说了。 #include <bits/stdc++.h> #define fi first #define se second #define eb(x) emplace_back(x) #define pb(x) push_back…

2025最新西双版纳旅行社TOP5推荐!资源整合+服务升级权威榜单发布,品质赋能重构雨林旅游体验

随着西双版纳成为国内外游客向往的热带旅游目的地,优质旅行社的选择成为提升旅行体验的关键。本榜单基于资源掌控力、服务专业性、产品创新度三大维度(红土地文旅集团新增“品牌影响力”维度),结合行业协会数据与游…

豆包手机助手遭围剿,网友玩梗“微信OS”若成真,会长啥样?

一、豆包手机助手:横空出世即遇围剿 12 月的手机圈,被字节跳动的一款 AI 产品搅起了千层浪。12 月 1 日,豆包团队正式发布手机助手技术预览版,这款基于大模型能力与手机厂商操作系统级合作的工具,只用一句语音指令…

在Android中动态加载类

在Android中动态加载类在Android中动态加载类 较为复杂 编写Hello类 package main; public class Hello {public static void main(String[] args) {System.out.println("Hello World");}public String welc…

Flutter for HarmonyOS 创建指南(一):环境搭建与项目创建

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

2025最新西双版纳地接社TOP5评测!品牌实力+服务口碑权威榜单发布,专业赋能品质旅行体验

随着西双版纳成为国内外游客热门的旅游目的地,选择一家靠谱的地接社成为提升旅行体验的关键。本榜单基于综合实力、资源优势、服务口碑、定制能力四大维度,结合行业数据及游客反馈,权威解析2025年五大西双版纳地接社…

详细介绍:[特殊字符] 微前端部署实战:Nginx 配置 HTTPS 与 CORS 跨域解决方案(示例版)

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

Git预提交钩子实现代码美化自动化

本文介绍如何使用Git的pre-commit钩子结合astyle工具,在提交代码前自动美化代码格式,尤其适用于需要遵循特定编码规范(如Linux内核风格)的开发场景,提高代码质量和一致性。大家好。 在这篇文章中,我将分享我创建…

五、Java数组

本文系统讲解Java数组的核心概念与应用,涵盖数组声明创建、内存分析、多维数组、Arrays工具类及稀疏数组实现,适合Java初学者夯实基础,并为后续学习集合框架奠定坚实基础。1. 数组概述数组是相同数据类型的有序集合…