102302114_比山布努尔兰_作业4

news/2025/12/9 20:21:48/文章来源:https://www.cnblogs.com/bishanbu/p/19322487

作业1

熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。
使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、“深证A股”3个板块的股票数据信息。

作业代码

点击查看代码
import time
import pymysql
from selenium import webdriver
from selenium.webdriver.chrome.service import Service
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from webdriver_manager.chrome import ChromeDriverManager# 数据库连接配置
DB_CONFIG = {"host": "localhost","user": "root","password": "123456","database": "stock_db","port": 3306,"charset": "utf8mb4"
}# 连接MySQL数据库函数
def get_db_connection():try:conn = pymysql.connect(host=DB_CONFIG["host"],user=DB_CONFIG["user"],password=DB_CONFIG["password"],database=DB_CONFIG["database"],port=DB_CONFIG["port"],charset=DB_CONFIG["charset"])print("数据库连接成功!")return connexcept Exception as e:print(f"数据库连接失败:{e}")return None# 爬取股票数据函数
def crawl_stock_data():# Chrome配置(我选择的是谷歌浏览器)chrome_options = webdriver.ChromeOptions()chrome_options.add_argument("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")chrome_options.add_argument("--disable-blink-features=AutomationControlled")# 初始化浏览器driver = webdriver.Chrome(service=Service(ChromeDriverManager().install()),options=chrome_options)wait = WebDriverWait(driver, 20)  # 延长等待时间# 目标网址url = "http://quote.eastmoney.com/center/gridlist.html#hs_a_board"driver.get(url)time.sleep(3)# 板块定位boards = {"沪深京A股": '//li[not(ancestor::ul[@class="lsub"])]/a[contains(@href, "#hs_a_board") and contains(text(), "沪深京A股")]',"上证A股": '//li[not(ancestor::ul[@class="lsub"])]/a[contains(@href, "#sh_a_board") and contains(text(), "上证A股")]',"深证A股": '//li[not(ancestor::ul[@class="lsub"])]/a[contains(@href, "#sz_a_board") and contains(text(), "深证A股")]'}# 连接数据库conn = get_db_connection()if not conn:driver.quit()returncursor = conn.cursor()try:for board_name, board_xpath in boards.items():print(f"\n开始爬取【{board_name}】数据...")# 1. 切换板块try:board_btn = wait.until(EC.element_to_be_clickable((By.XPATH, board_xpath)))driver.execute_script("arguments[0].click();", board_btn)time.sleep(4)print(f"成功切换到【{board_name}】")except Exception as e:print(f"切换【{board_name}】失败:{str(e)}")continue# 2. 提取表格数据try:stock_table_xpath = '//tbody[.//a[contains(@href, "quote.eastmoney.com/unify/r/")]]'# 等待股票表格加载完成wait.until(EC.presence_of_element_located((By.XPATH, stock_table_xpath)))table_body = driver.find_element(By.XPATH, stock_table_xpath)driver.execute_script("arguments[0].scrollIntoView({behavior: 'smooth', block: 'end'});",table_body)time.sleep(3)  # 等待滚动后加载更多数据# 获取表格中所有股票行rows = table_body.find_elements(By.TAG_NAME, "tr")print(f"【{board_name}】共找到 {len(rows)} 条股票数据")# 解析每行数据for row in rows:cols = row.find_elements(By.TAG_NAME, "td")if len(cols) < 13:  # 这里是为了确保列数完整continuestock_data = {"bStockNo": cols[1].text.strip(),"bStockName": cols[2].text.strip(),"latestPrice": cols[4].text.strip(),"priceChangePercent": cols[5].text.strip(),"priceChange": cols[6].text.strip(),"volume": cols[7].text.strip(),"turnover": cols[8].text.strip(),"amplitude": cols[9].text.strip(),"highest": cols[10].text.strip(),"lowest": cols[11].text.strip(),"openToday": cols[12].text.strip(),"closeYesterday": cols[13].text.strip()}# 类型转换for key in stock_data:if stock_data[key] == "":stock_data[key] = Noneif key in ["latestPrice", "priceChange", "highest", "lowest", "openToday", "closeYesterday"]:if stock_data[key] is not None:try:stock_data[key] = float(stock_data[key])except ValueError:stock_data[key] = None# 插入数据库sql = """INSERT INTO stock_data (bStockNo, bStockName, latestPrice, priceChangePercent, priceChange,volume, turnover, amplitude, highest, lowest, openToday, closeYesterday) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)ON DUPLICATE KEY UPDATEbStockName=%s, latestPrice=%s, priceChangePercent=%s, priceChange=%s,volume=%s, turnover=%s, amplitude=%s, highest=%s, lowest=%s,openToday=%s, closeYesterday=%s"""sql_params = (stock_data["bStockNo"], stock_data["bStockName"], stock_data["latestPrice"],stock_data["priceChangePercent"], stock_data["priceChange"], stock_data["volume"],stock_data["turnover"], stock_data["amplitude"], stock_data["highest"],stock_data["lowest"], stock_data["openToday"], stock_data["closeYesterday"],stock_data["bStockName"], stock_data["latestPrice"], stock_data["priceChangePercent"],stock_data["priceChange"], stock_data["volume"], stock_data["turnover"],stock_data["amplitude"], stock_data["highest"], stock_data["lowest"],stock_data["openToday"], stock_data["closeYesterday"])cursor.execute(sql, sql_params)conn.commit()except Exception as e:print(f"提取【{board_name}】数据失败:{str(e)}")continueprint("\n所有板块数据爬取完成!")finally:cursor.close()conn.close()driver.quit()if __name__ == "__main__":crawl_stock_data()

运行结果

image
image

心得体会

通过这个实验,我大概了解了selenium的工作原理

作业2

要求:
熟练掌握 Selenium 查找HTML元素、实现用户模拟登录、爬取Ajax网页数据、等待HTML元素等内容。
使用Selenium框架+MySQL爬取中国mooc网课程资源信息(课程号、课程名称、学校名称、主讲教师、团队成员、参加人数、课程进度、课程简介)

作业代码

点击查看代码
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import NoSuchElementException, TimeoutException
import pymysql
import time
import traceback# 配置MySQL数据库
DB_CONFIG = {"host": "localhost","user": "root","password": "123456","database": "icourse_db","port": 3306,"charset": "utf8mb4"
}# 用来操作数据库的函数
def get_mysql_connection():try:conn = pymysql.connect(host=DB_CONFIG["host"],user=DB_CONFIG["user"],password=DB_CONFIG["password"],port=DB_CONFIG["port"],charset=DB_CONFIG["charset"])cursor = conn.cursor()# 自动创建数据库cursor.execute(f"CREATE DATABASE IF NOT EXISTS {DB_CONFIG['database']} DEFAULT CHARACTER SET {DB_CONFIG['charset']}")conn.select_db(DB_CONFIG["database"])print("MySQL数据库连接+创建成功!")return connexcept Exception as e:print(f"MySQL连接失败:{e}")traceback.print_exc()return Nonedef init_course_table(conn):# 初始化课程表cursor = conn.cursor()# 核心修复:去掉course_intro的DEFAULT ''create_table_sql = '''CREATE TABLE IF NOT EXISTS course_detail (id INT PRIMARY KEY AUTO_INCREMENT COMMENT '自增ID',course_name VARCHAR(255) NOT NULL COMMENT '课程名称',school_name VARCHAR(100) DEFAULT '' COMMENT '学校名称',main_teacher VARCHAR(100) DEFAULT '' COMMENT '主讲教师',teacher_team VARCHAR(255) DEFAULT '' COMMENT '教师团队',attend_count VARCHAR(20) DEFAULT '0' COMMENT '参加人数',course_progress VARCHAR(100) DEFAULT '' COMMENT '课程进度',course_intro TEXT COMMENT '课程简介'  -- 移除DEFAULT '') ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='中国大学MOOC课程表';'''cursor.execute(create_table_sql)conn.commit()return cursordef save_course_to_mysql(cursor, conn, course_data):# 保存课程数据到MySQLtry:insert_sql = '''INSERT INTO course_detail (course_name, school_name, main_teacher, teacher_team,attend_count, course_progress, course_intro) VALUES (%s, %s, %s, %s, %s, %s, %s)'''sql_params = (course_data["course_name"],course_data["school_name"],course_data["main_teacher"],course_data["teacher_team"],course_data["attend_count"],course_data["course_progress"],course_data["course_intro"])cursor.execute(insert_sql, sql_params)conn.commit()except Exception as e:conn.rollback()print(f"保存课程数据失败: {e}")traceback.print_exc()# 爬取函数 
def init_edge_browser():#初始化我选择的Edge浏览器edge_options = webdriver.EdgeOptions()edge_options.add_experimental_option("excludeSwitches", ["enable-automation"])edge_options.add_argument("--start-maximized")driver = webdriver.Edge(options=edge_options)driver.implicitly_wait(6)return driverdef mooc_login_operation(driver):# 登录MOOCtry:login_trigger_btn = driver.find_element(By.CLASS_NAME, '_3uWA6')login_trigger_btn.click()time.sleep(1)wait = WebDriverWait(driver, 10)login_iframe_elem = wait.until(EC.presence_of_element_located((By.XPATH, "//div[@class='ux-login-set-container']//iframe")))driver.switch_to.frame(login_iframe_elem)mobile_input_box = driver.find_element(By.ID, 'phoneipt')mobile_input_box.send_keys('18506021680')pwd_input_box = driver.find_element(By.XPATH, "//input[@placeholder='请输入密码']")pwd_input_box.send_keys("Nn125513")login_submit_btn = driver.find_element(By.ID, 'submitBtn')login_submit_btn.click()time.sleep(2)print("MOOC账号登录操作执行完成")except Exception as e:print(f"登录流程异常: {e}")traceback.print_exc()def scroll_load_more_courses(driver, max_scroll_times=5):# 滚动加载课程print("\n开始滚动加载课程列表...")scroll_times = 0prev_page_height = driver.execute_script("return document.body.scrollHeight")while scroll_times < max_scroll_times:driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")time.sleep(2)curr_page_height = driver.execute_script("return document.body.scrollHeight")scroll_times += 1if curr_page_height == prev_page_height:print(f"第{scroll_times}次滚动后无新内容,停止加载")breakprev_page_height = curr_page_heightprint(f"第{scroll_times}次滚动完成,当前页面高度: {curr_page_height}")def parse_single_course_info(course_elem):# 解析一个个课程course_info = {"course_name": "未知课程","school_name": "","main_teacher": "","teacher_team": "","attend_count": "0","course_progress": "","course_intro": ""}try:if course_elem.find_elements(By.CSS_SELECTOR, "div._1vfZ-"):course_info["course_name"] = course_elem.find_element(By.CSS_SELECTOR, "div._1vfZ-").textif course_elem.find_elements(By.CSS_SELECTOR, "a._3vJDG"):course_info["school_name"] = course_elem.find_element(By.CSS_SELECTOR, "a._3vJDG").textelif course_elem.find_elements(By.CSS_SELECTOR, "a._3t_C8"):course_info["school_name"] = course_elem.find_element(By.CSS_SELECTOR, "a._3t_C8").textteacher_elems = course_elem.find_elements(By.CSS_SELECTOR, "a._3t_C8")if teacher_elems:course_info["main_teacher"] = teacher_elems[0].textcourse_info["teacher_team"] = "、".join([t.text for t in teacher_elems if t.text])if course_elem.find_elements(By.CSS_SELECTOR, "div._CWjg"):attend_text = course_elem.find_element(By.CSS_SELECTOR, "div._CWjg").textcourse_info["attend_count"] = attend_text.replace('参加', '').strip()if course_elem.find_elements(By.CSS_SELECTOR, "div._1r-No"):course_info["course_progress"] = course_elem.find_element(By.CSS_SELECTOR, "div._1r-No").textif course_elem.find_elements(By.CSS_SELECTOR, "div._3JEMz"):course_info["course_intro"] = course_elem.find_element(By.CSS_SELECTOR, "div._3JEMz").textprint(f"\n【解析第 {parse_single_course_info.count + 1} 条课程】")print(f"课程名:{course_info['course_name']}")print(f"学校:{course_info['school_name']} | 主讲:{course_info['main_teacher']}")print(f"参与人数:{course_info['attend_count']} | 进度:{course_info['course_progress']}")parse_single_course_info.count += 1return course_infoexcept Exception as e:print(f"解析单条课程失败: {e}")traceback.print_exc()return Noneparse_single_course_info.count = 0# 主执行流程 
if __name__ == "__main__":# 初始化浏览器driver = init_edge_browser()driver.get('https://www.icourse163.org/')time.sleep(1)# 登录mooc_login_operation(driver)# 访问搜索页面search_url = 'https://www.icourse163.org/search.htm?search=%E8%AE%A1%E7%AE%97%E6%9C%BA#/'driver.get(search_url)time.sleep(3)# 滚动加载课程scroll_load_more_courses(driver, max_scroll_times=5)# 获取课程列表wait = WebDriverWait(driver, 10)course_list = []try:course_list = wait.until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "div._3NYsM")))print(f"\n成功定位到 {len(course_list)} 个课程卡片")except Exception as e:print(f"获取课程列表异常: {e}")traceback.print_exc()# 连接MySQL并保存数据if course_list:# 建立MySQL连接mysql_conn = get_mysql_connection()if not mysql_conn:driver.quit()exit(1)# 初始化课程表mysql_cursor = init_course_table(mysql_conn)# 遍历解析课程并保存total_parsed = 0for course_elem in course_list:parsed_data = parse_single_course_info(course_elem)if parsed_data:save_course_to_mysql(mysql_cursor, mysql_conn, parsed_data)total_parsed += 1# 验证MySQL数据print(f"\n{'*' * 60}")print(f"数据保存完成,共解析 {total_parsed} 条有效课程")print(f"存储位置:MySQL -> {DB_CONFIG['database']}.course_detail")# 查询前3条数据验证mysql_cursor.execute("SELECT course_name, school_name, attend_count FROM course_detail LIMIT 3")print("\nMySQL前3条记录预览:")for idx, record in enumerate(mysql_cursor.fetchall(), 1):print(f"{idx}. 课程:{record[0]} | 学校:{record[1]} | 人数:{record[2]}")# 关闭MySQL连接mysql_cursor.close()mysql_conn.close()else:print("\n未找到任何课程卡片,跳过数据库操作")# 关闭浏览器print(f"\n程序执行完成,5秒后自动关闭浏览器...")time.sleep(5)driver.quit()

运行结果

image
image
image
image
image

心得体会

做完这个实验我是第一次切身感受到了代码的强大,原来代码真的可以像人一样去找到网站搜索框去搜索信息,真的很震撼。

作业3

熟练掌握 Selenium 查找HTML元素、实现用户模拟登录、爬取Ajax网页数据、等待HTML元素等内容。
使用Selenium框架+MySQL爬取中国mooc网课程资源信息(课程号、课程名称、学校名称、主讲教师、团队成员、参加人数、课程进度、课程简介)

开通MapReduce服务

购买集群
image
购买弹性公网
image
配置安全组
image

Python脚本生成测试数据

ssh远程连接并Python脚本生成测试数据
image
image

配置Kafka

安装Kafka客户端
image
创建并查看topic信息
image

安装Flume客户端

image
image
image

配置Flume采集数据

image

心得体会

通过这个实验,我学会了怎么使用华为云上的Kafka、Flume等工具帮助我计算一些复杂的案例。

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

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

相关文章

2025年12月济南艺考画室最新推荐:济南大道画室,济南艺考画室、济南画室哪家好、济南画室推荐、山东美术艺考培训、山东画室个性化教学新标杆

随着美术艺考竞争日益激烈、教学标准化要求提升及学生个性化发展需求增加,优质画室已从大城市集中逐步扩展至地方深耕,2025年艺考培训市场规模预计持续增长。但市场扩张也带来画室教学水平、师资力量、升学成果参差不…

记一次磁盘占满的问题

说明 之前搭建的lobehub/lobe-chat网页AI问答突然不能用了。 于是重启docker遇到: yangx@ak:~$ docker run 23576ea8e726 docker: Error response from daemon: mkdir /var/lib/docker/overlay2/70e1042a088ffe1a6d26…

Redis提供的原子性命令

目录Redis提供的原子性命令主要类别的原子性命令:1. 字符串(String)原子操作2. 列表(List)原子操作3. 集合(Set)原子操作4. 哈希(Hash)原子操作5. 有序集合(Sorted Set)原子操作6. 位图(Bitmap)原子操作7…

多业态连锁环境管理系统:AI + 机器人闭环,坪效提升 16%

门店环境本是沉默的,却在无声处酿成大祸:高峰无人知地面湿滑,夜间无人见灯闪,雨天无人管玻璃污——2025年,环境设施异常导致的综合损失平均占运营成本19%,保洁+维修双线超支,数据孤岛让决策如盲。全场景痛点全面…

2025年12月室内水上乐园厂家推荐:山东汇川,儿童水上乐园、大型水上乐园、主题水上乐园、室外水上乐园、恒温泳池、室 泳池、全场景适配新标杆

随着文旅产业升级、消费需求多元化及健康理念普及,水上游乐与泳池设备行业迎来快速发展期,2025 年市场规模预计持续扩大。但市场增长也带来厂商产品质量、场景适配性、服务专业性参差不齐的问题,企业及投资者在选购…

2025雅思培训班怎么选?这5家高性价比机构帮你高效提分

2025雅思培训班怎么选?这5家高性价比机构帮你高效提分一、雅思选课三大痛点解析:为什么你总在无效对比? 在雅思备考的漫漫征途中,选对培训班就如同找到了一把开启成功之门的钥匙。然而,面对市场上琳琅满目的雅思培…

实用指南:「腾讯云NoSQL」技术之向量数据库篇:自研分布式向量数据库,实现毫秒级时序一致备份的挑战和实践

实用指南:「腾讯云NoSQL」技术之向量数据库篇:自研分布式向量数据库,实现毫秒级时序一致备份的挑战和实践2025-12-09 20:11 tlnshuju 阅读(0) 评论(0) 收藏 举报pre { white-space: pre !important; word-wrap:…

Semaphore、CountDownLatch、ReentrantLock使用场景简单说说

目录Semaphore、CountDownLatch、ReentrantLock使用场景简单说说1. Semaphore(信号量)2. CountDownLatch(倒计时门闩)3. ReentrantLock(可重入锁)对比总结简单记忆三个并发工具的简单示例1. Semaphore 示例 - 停…

LATTICE HW-USBN-2B 高速下载器凭什么是销冠

LATTICE HW-USBN-2B 高速下载器凭什么是销冠 1). 支持windows7,Windows10 操作系统,两个操作系统非常稳定不断线。2). 支持JTAG 模式,速度快,最高30Mb/s,调试serdes core,不会像hw-usbn-2a出现错误。如这种错误…

py-lambda-map-list随笔

py-lambda-map-list随笔 匿名函数lambda lambda 表达式用于创建 小型、匿名 的单行函数。 语法:lambda arguments: expression很方便的map()用于及其方便地映射 把相同的操作(如lambda表达式)映射到后者(如列表上)…

2025年12月水上乐园设备厂家最新推荐:昊至泉充气水上乐园设备、室内水上乐园设备、户外水上乐园设备、大型水上乐园设备、漂流河水上乐园设备、打造安全创新个性化水上娱乐新标准

随着全民休闲娱乐需求增长及文旅产业升级,水上乐园作为夏季热门旅游目的地,其设备安全性、创新性及个性化设计已成为投资运营者的核心考量。2025年,市场对水上乐园设备的要求已从基础功能转向安全高效、主题鲜明、适…

杂题选记

记录一些我觉得比较有意思的题目。难度差异可能会很大。 书信 给一个字符串 \(S\),对于 \(S\) 中的每一类字符,可以选择一个区间 \([l,r]\) 保留,保留的字母间相对顺序不变。 每一个位置有权值 \(w_i\)。 求将 \(S\…

2025年12月铝材厂家推荐榜:廊坊国美铝业,工业铝材、门窗铝材、3C铝材、通用铝材、多领域铝材定制与绿色生产标杆

随着 2025 年国内基建项目集中开工、新能源产业加速扩张及绿色建筑标准全面落地,铝材作为工业制造与建筑领域的核心基础材料,市场需求持续攀升。但当前市场上厂商技术水平、产品适配能力及环保合规性差异显著,企业在…

Qt 文本转语言(QTextToSpeech类)详解 - 实践

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

AWS发布网络扫描指南:构建更安全云环境的守则

亚马逊云科技(AWS)正式发布针对客户工作负载的网络扫描行为指导原则。该指南旨在帮助合规扫描工具获取更准确数据,减少滥用报告,并提升整体互联网安全,涵盖了扫描行为的可观测性、可识别性、协作性与保密性四大核…

# 题解#洛谷P2880 Balanced Lineup #ST表#

P2880 [USACO07JAN] Balanced Lineup G - 洛谷 分析f[i][j]记录以i开头,长度为2^i的子段的最值f[i][j+1]=max( f[i][j] , f[i+2^(j-1)][j-1] )代码实现 #include<bits/stdc++.h> #define int long long #defin…

2025年12月包头保洁公司最新推荐:信达家政,包头保洁开荒、包头高空清洗保洁、包头保姆公司、包头保姆家政、包头保姆月嫂、包头保姆护工、服务品质新标准

随着城市生活节奏加快及家庭服务需求多元化发展,家政服务行业正朝着专业化、标准化、精细化的方向升级。2025年,市场对高品质、可信赖的家政服务需求持续增长,但服务机构水平参差不齐、服务标准不一、人员素质差异大…

机器视觉测量与建模

基于机器视觉的空间信息数据获取与处理技术在当今发展迅速、应用前景巨大,它与计算机视觉、计算机图像学、机器人视觉导航、测绘遥感、地理信息系统等学科方向密切相关。本课程将系统地讲解介绍基于机器视觉的三维空间…

2025最值得报的雅思封闭班:高性价比/冲高分/打基础三类优选清单

2025最值得报的雅思封闭班:高性价比/冲高分/打基础三类优选清单一、2025 雅思封闭班选课指南:五维评测体系揭秘 在雅思备考白热化的当下,封闭式培训以沉浸式学习优势成为提分 “加速器”。本文联合 ETS 官方合作机构…

[Java EE] 多线程 -- 初阶(1) - 详解

[Java EE] 多线程 -- 初阶(1) - 详解pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monac…