Just do it!

数据采集与融合实验四

码云仓库👉https://gitee.com/poetry-joy/crawl_project

作业链接👉作业四 - 作业 - 2024数据采集与融合技术实践 - 班级博客 - 博客园

注:代码块可滑动
在下052205144张诗悦

一、作业①⛵

要求:熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内 容。 ▪ 使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、 “深证A股”3个板块的股票数据信息。 o 候选网站:东方财富网: http://quote.eastmoney.com/center/gridlist.html#hs_a_board o 输出信息:MYSQL数据库存储和输出格式如下,表头应是英文命名例如:序号 id,股票代码:bStockNo……,由同学们自行定义设计表头:

输出信息:

Gitee 文件夹链接👉实验四/task1 · 诗悦/2022级数据采集与融合技术 - 码云 - 开源中国

结果👉实验四/task1/stocks.csv · 诗悦/2022级数据采集与融合技术 - 码云 - 开源中国

1)作业代码和图片

①task1.py

# _*_ coding : utf-8 _*_
# @Time :  13:44
# @Author : yoyo
# @File : task1
# @Project : pythonProject

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 StaleElementReferenceException
import sqlite3
import time

# 启动 Selenium WebDriver
def get_driver():
    chrome_options = webdriver.ChromeOptions()
    # chrome_options .add_argument('--headless')  # 不显示浏览器界面
    chrome_options.add_argument('--disable-gpu')
    driver = webdriver.Chrome(options=chrome_options)
    return driver

# 连接SQLite数据库
def connect_sqlite():
    conn = sqlite3.connect('stock数据库_result.db')
    return conn

# 创建股票数据表
def create_table():
    conn = connect_sqlite()
    cursor = conn.cursor()

    # 创建股票数据表
    cursor.execute('''CREATE TABLE IF NOT EXISTS stocks (
                        序号 INTEGER PRIMARY KEY,
                        股票代码 TEXT NOT NULL,
                        股票名称 TEXT NOT NULL,
                        最新报价 TEXT NOT NULL,
                        涨跌幅 TEXT NOT NULL,
                        涨跌额 TEXT NOT NULL,
                        成交量 TEXT NOT NULL,
                        成交额 TEXT NOT NULL,
                        振幅 TEXT NOT NULL,
                        最高 TEXT NOT NULL,
                        最低 TEXT NOT NULL,
                        今开 TEXT NOT NULL,
                        昨收 TEXT NOT NULL,
                        market TEXT NOT NULL)''')

    conn.commit()
    cursor.close()
    conn.close()

# 插入数据到SQLite
def insert_stock_data(stock_data):
    connection = connect_sqlite()
    cursor = connection.cursor()

    insert_query = '''
    INSERT INTO stocks (股票代码, 股票名称, 最新报价, 涨跌幅, 涨跌额, 成交量, 成交额, 振幅, 最高, 最低, 今开, 昨收, market)
    VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?)
    '''

    try:
        cursor.executemany(insert_query, stock_data)
        connection.commit()
    except Exception as e:
        print(f"插入数据时发生错误: {e}")
    finally:
        cursor.close()
        connection.close()

# 获取表格行数据(带重试机制)
def get_table_rows(driver):
    retries = 3
    while retries > 0:
        try:
            table = driver.find_element(By.ID, 'table_wrapper-table')
            rows = table.find_elements(By.TAG_NAME, 'tr')
            return rows
        except StaleElementReferenceException:
            print("表格元素过期,重新获取...")
            retries -= 1
            time.sleep(2)  # 等待页面重新加载
    raise Exception("多次重试后仍未获取到表格元素。")

# 抓取东方财富网股票数据
def scrape_stock_data(market, driver):
    url = 'http://quote.eastmoney.com/center/gridlist.html#hs_a_board'
    driver.get(url)

    # 根据不同市场选择相应的板块
    if market == "沪深京A股":
        driver.find_element(By.LINK_TEXT, '沪深京A股').click()
        # driver.execute_script("window.scrollTo(0, 0);")
    elif market == "上证A股":
        driver.find_element(By.LINK_TEXT, '上证A股').click()
        # driver.execute_script("window.scrollTo(0, 0);")
    elif market == "深证A股":
        driver.find_element(By.LINK_TEXT, '深证A股').click()
        # driver.execute_script("window.scrollTo(0, 0);")

    # 等待页面加载完成,直到表格加载完毕
    WebDriverWait(driver, 20).until(
        EC.presence_of_element_located((By.ID, 'table_wrapper-table'))
    )
    time.sleep(2)
    driver.execute_script("window.scrollTo(0, 0);")
    # 获取股票数据表格行
    rows = get_table_rows(driver)
    # print(rows)

    stock_data = []

    for row in rows[1:]:  # 跳过表头
        try:
            # 重新查找列元素,防止列失效
            columns = row.find_elements(By.TAG_NAME, 'td')
            print(columns)
            stock_code = columns[1].text.strip()  # 股票代码
            stock_name = columns[2].text.strip()  # 股票名称
            current_price = columns[4].text.strip()  # 最新报价
            change_rate = columns[5].text.strip()
            change_num = columns[6].text.strip()
            turnover = columns[7].text.strip()  # 成交量
            price = columns[8].text.strip()  # 成交额
            amplitude = columns[9].text.strip()  # 振幅
            max_value = columns[10].text.strip()
            min_value = columns[11].text.strip()
            today = columns[12].text.strip()
            yes = columns[13].text.strip()

            stock_data.append((stock_code, stock_name, current_price, change_rate, change_num, turnover, price,
                               amplitude, max_value, min_value, today, yes, market))

        except StaleElementReferenceException:
            print("行数据过期,跳过此行...")
            continue
        except Exception as e:
            print(f"处理行数据时发生错误: {e}")
            continue

    # 插入数据到数据库
    insert_stock_data(stock_data)

# 主程序
if __name__ == '__main__':
    create_table()

    driver = get_driver()  # 启动浏览器

    try:
        for market in ["沪深京A股", "上证A股", "深证A股"]:
            scrape_stock_data(market, driver)
            print(f"{market} 数据爬取并存储成功!")
        print("所有数据爬取并存储成功!")
    except Exception as e:
        print(f"发生错误: {e}")
    finally:
        driver.quit()  # 关闭浏览器

②运行结果截图

2)作业心得

①在模拟点击上证A股和深圳A股时,始终会输出一堆堆栈信息,导致无法正常运行,经过长时间的排查,才发现是ajax数据还没加载好,从而导致每次报错的点都不一样!!!

②在模拟点击上证A股和深圳A股时,如何处理了翻页逻辑,必须定位回原来的窗口,否则有可能无法定位到上证A股和深圳A股这两个超链接文本

二、作业 ②🐟

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

输出信息:

Gitee 文件夹链接👉实验四/task2 · 诗悦/2022级数据采集与融合技术 - 码云 - 开源中国

结果👉实验四/task2/courses.csv · 诗悦/2022级数据采集与融合技术 - 码云 - 开源中国

1)作业代码和图片

①task2.py

这里我的账号密码做了脱敏处理,如果需要模拟登录,可在对应位置输入自己的账号密码

# _*_ coding : utf-8 _*_
# @Time :  13:39
# @Author : yoyo
# @File : task2
# @Project : pythonProject

from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import sqlite3
import time

# 初始化 SQLite 数据库连接
def connect_sqlite():
    conn = sqlite3.connect('MOOC.db')
    return conn

# 创建课程数据表
def create_table():
    conn = connect_sqlite()
    cursor = conn.cursor()

    cursor.execute('''
    CREATE TABLE IF NOT EXISTS courses (
        Id  INTEGER PRIMARY KEY,
        cCourse TEXT,
        cCollege TEXT,
        cTeacher TEXT,
        cTeam TEXT,
        cCount INTEGER,
        cProcess TEXT,
        cBrief TEXT
    )
    ''')

    conn.commit()
    cursor.close()
    conn.close()

# 插入课程数据到 SQLite
def insert_course_data(course_data):
    conn = connect_sqlite()
    cursor = conn.cursor()

    insert_query = '''
    INSERT OR REPLACE INTO courses (cCourse, cCollege, cTeacher, cTeam, cCount, cProcess, cBrief)
    VALUES (?, ?, ?, ?, ?, ?, ?)
    '''
    cursor.execute(insert_query, course_data)
    conn.commit()
    cursor.close()
    conn.close()

# 启动 Selenium WebDriver
def get_driver():
    chrome_options = webdriver.ChromeOptions()
    # chrome_options.add_argument('--headless')  # 不显示浏览器界面
    chrome_options.add_argument('--disable-gpu')
    driver = webdriver.Chrome(options=chrome_options)
    return driver

# 模拟登录
def login(driver, username, password):
    driver.get("https://www.icourse163.org/")
    # time.sleep(2)
    # 定位并点击登录按钮
    # login_button = driver.find_element(By.LINK_TEXT, "登录 | 注册")  # 根据按钮文本定位
    login_button = driver.find_element(By.XPATH, '//*[@id="j-topnav"]/div')
    login_button.click()

    time.sleep(2)
    # 等待 iframe 加载完成
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.TAG_NAME, "iframe")))

    # 切换到 iframe
    iframe = driver.find_element(By.XPATH,'/html/body/div[13]/div[2]/div/div/div/div/div/div[1]/div/div[1]/div[2]/div[2]/div[1]/div/iframe')
    driver.switch_to.frame(iframe)



    # 输入用户名和密码
    WebDriverWait(driver, 10).until(EC.presence_of_element_located((By.ID, "phoneipt")))
    username_field = driver.find_element(By.XPATH,'//*[@id="phoneipt"]')
    password_field = driver.find_element(By.XPATH,'//*[@id="login-form"]/div/div[4]/div[2]/input[2]')

    username_field.send_keys(username)
    password_field.send_keys(password)
    # time.sleep(100)
    # 等待登录成功后,进入用户页面
    time.sleep(1)
    button = driver.find_element(By.XPATH, '/html/body/div[2]/div[2]/div[2]/form/div/div[6]/a')
    button.click()

    # 等待验证登录
    WebDriverWait(driver, 60).until(EC.url_changes(driver.current_url))
    driver.switch_to.default_content()  # 切回主内容
    time.sleep(2)


# 处理弹窗,点击同意按钮
def handle_popup(driver):
    try:
        # 等待弹窗的“同意”按钮出现
        WebDriverWait(driver, 10).until(
            EC.presence_of_element_located((By.XPATH, "//button[text()='同意']")))  # 根据按钮文本定位

        # 定位并点击“同意”按钮
        agree_button = driver.find_element(By.XPATH, "//button[text()='同意']")
        agree_button.click()
        print("点击了同意按钮")

    except Exception as e:
        print(f"没有找到弹窗或按钮: {e}")

def simulate_scroll():
    # 获取页面高度
    page_height = driver.execute_script("return document.body.scrollHeight")
    # 定义滚动步长和间隔时间
    scroll_step = 5  # 每次滚动的距离
    scroll_delay = 5  # 每次滚动的间隔时间(秒)
    # 模拟慢慢滚动
    current_position = 0
    while current_position < page_height:
        # 计算下一个滚动位置
        next_position = current_position + scroll_step
        # 执行滚动动作
        driver.execute_script(f"window.scrollTo(0, {next_position});")
        # 等待一段时间
        driver.implicitly_wait(scroll_delay)
        # 更新当前滚动位置
        current_position = next_position

# 获取课程列表数据
def scrape_courses(driver,course):
    time.sleep(2)
    # 等待搜索框可点击
    input = WebDriverWait(driver, 10, 0.5).until(
        EC.element_to_be_clickable((By.XPATH, '//*[@id="j-indexNav-bar"]/div/div/div/div/div[7]/div[1]/div/div[1]/div[1]/span/input'))
    )
    input.send_keys(course)
    input.send_keys(Keys.RETURN)
    simulate_scroll()   # 加载图片
    time.sleep(2)
    courses = driver.find_elements(By.XPATH,'/html/body/div[4]/div[2]/div[2]/div[2]/div/div[6]/div[2]/div[1]/div/div/div')
    for course in courses:
        course_name = course.find_elements(By.XPATH, './div[2]/div/div/div[1]/a[1]/span')[0].text.strip()
        school_name = course.find_elements(By.XPATH, './div[2]/div/div/div[2]/a[1]')[0].text.strip()
        elements = course.find_elements(By.XPATH, './div[2]/div/div/div[2]/a[2]')
        instructor = elements[0].text if elements else None
        team_member = instructor
        elements = course.find_elements(By.XPATH, './div[2]/div/div/div[3]/span[2]')
        participants = elements[0].text if elements else None
        elements = course.find_elements(By.XPATH, './div[2]/div/div/div[3]/div/span[2]')
        progress= elements[0].text if elements else None
        elements = course.find_elements(By.XPATH, './div[2]/div/div/a/span')
        description= elements[0].text if elements else None
        print(course_name)
        # 插入课程数据
        course_data = (course_name, school_name, instructor, team_member, participants, progress, description)
        insert_course_data(course_data)


# 主程序
if __name__ == "__main__":
    create_table()  # 创建课程数据表

    driver = get_driver()

    course="数据库"
    login(driver, "", "")  # 输入你的手机号和密码
    handle_popup(driver)  # 处理弹窗,点击同意按钮
    time.sleep(5)
    scrape_courses(driver,course)
    print("所有课程数据爬取并存储成功!")

    driver.quit()

②结果截图

2)作业心得

①在模拟用户登录时,我始终无法定位到手机号码的输入框,经过老师的点播后,发现首先要将driver切换到控制iframe才能定位其上面的元素,即手机号码输入框,密码输入框还有登录按钮。

iframe=……
switch_to_frame(iframe)

②iframe窗体输入用户登陆信息后,释放iframe回到之前的主页面进行操作,并等待若干时间

self.browser.switch_to.default_content()
time.sleep()

③窗体根据出现的先后产生索引值,0是第一个,-1是最后一个,依据当前活跃或焦点的窗体的切换,以准确的操控浏览器页面上去找元素,并操作相关元素。

三、作业③ 💬

要求:
• 掌握大数据相关服务,熟悉Xshell的使用
• 完成文档 华为云_大数据实时分析处理实验手册-Flume日志采集实验(部分)v2.docx 中的任务,即为下面5个任务,具体操作见文档。

输出信息:

1)实验关键步骤或结果截图。

• 环境搭建:
任务一:开通MapReduce服务

①选择弹性公网IP

②查看购买的弹性公网IP

③开通MapReduce服务

④集群配置:硬件配置

⑤给集群的master节点绑定弹性IP

⑥修改安全组规则

• 实时分析开发实战:
任务一:Python脚本生成测试数据

任务二:配置Kafka

①下载安装并配置Kafka

②校验下载的客户端文件包

③查看解压后文件

④客户端运行环境安装成功

⑤查看topic信息

任务三: 安装Flume客户端

①下载Flume客户端

②校验下载的客户端文件包

③客户端运行环境安装成功

任务四:配置Flume采集数据

①配置Flume

此部分截图忘记保存了QAQ

②重启Flume服务

③Flume到Kafka目前是打通的

2)作业心得

1、问题记录:
①下载安装并配置Kafka的任务中,我的文件下载到了我没有绑定弹性公网IP的master节点上,导致我PUTTY目前连接的节点目录下没有对应的文件夹及文件,于是我解绑对应的master节点,查询对应master节点的地址,将弹性公网IP绑定到正确的master节点即可找到对应的文件及文件夹
②在队列的连通性测试中,由于写错了MySQL的端口号(默认为3306),我写错为9092 ,导致地址始终不可达,浪费了许多时间
2、实践心得:
我非常详细的了解到了华为云鲲鹏大数据平台的架构和功能。在实验过程中,我总结了成功的经验和方法,包括环境搭建、数据处理、实时分析等方面的技巧和经验。这些经验将对我未来的大数据实时分析工作产生积极的指导作用。我也发现了自己的不足之处,如对某些工具的不熟悉、数据处理效率有待提高。

posted on 2024-11-13 23:06  喜羊羊~~~  阅读(11)  评论(0编辑  收藏  举报

导航