数据采集与融合技术第四次作业

学号姓名 102202132 郑冰智
这个作业要求在哪里 https://edu.cnblogs.com/campus/fzu/2024DataCollectionandFusiontechnology/homework/13288
这个作业的目标 熟悉掌握selenium、查找HTML元素、实现用户模拟登录、爬取Ajax网页数据、等待HTML元素以及华为云日志采集实验等内容
实验四仓库地址 https://gitee.com/zheng-bingzhi/2022-level-data-collection/tree/master/实验四

一、作业①:

要求:

  • 熟练掌握 Selenium 查找HTML元素、爬取Ajax网页数据、等待HTML元素等内容。候选网站:东方财富网:http://quote.eastmoney.com/center/gridlist.html#hs_a_board
  • 使用Selenium框架+ MySQL数据库存储技术路线爬取“沪深A股”、“上证A股”、“深证A股”3个板块的股票数据信息。

输出信息: MYSQL数据库存储和输出格式如下,表头应是英文命名例如:序号id,股票代码:bStockNo……,由同学们自行定义设计表头:

序号 股票代码 股票名称 最新报价 涨跌幅 涨跌额 成交量 成交额 振幅 最高 最低 今开 昨收
1 688093 N世华 28.47 62.22% 10.92 26.13万 7.6亿 22.34 32.0 28.08 30.2 17.55
2 ...... ...... ...... ...... ...... ...... ...... ...... ...... ...... ......

Gitee文件夹链接:https://gitee.com/zheng-bingzhi/2022-level-data-collection/blob/master/实验四/gupiao.py

1.1实验代码及结果:

1.1.1核心代码:

  • scrape_board(self, board_name, table_name): 爬取特定板块数据的方法。首先打开东方财富网的板块列表页面,然后根据传入的板块名称点击相应的链接。页面加载后,它提取表格中的数据,并调用 save_to_db 方法将数据保存到数据库。
  • 使用rows = self.driver.find_elements(By.XPATH, '//tr[@class="odd" or @class="even"]')的方法提取内容。
  • board_link = self.driver.find_element(By.CSS_SELECTOR, f'a[href="{board_links[board_name]}"]')使用By.CSS_SELECTOR寻找不同模块并在浏览器中完成点击功能。
    board_link.click()
 def scrape_board(self, board_name, table_name):
        # 点击不同的板块
        self.driver.get("https://quote.eastmoney.com/center/gridlist.html")
        time.sleep(2)

        # 根据板块名称点击相应链接
        board_links = {
            "hs_a": "#hs_a_board",
            "sh_a": "#sh_a_board",
            "sz_a": "#sz_a_board"
        }
        board_link = self.driver.find_element(By.CSS_SELECTOR, f'a[href="{board_links[board_name]}"]')
        board_link.click()
        time.sleep(3)  # 等待页面加载

        # 提取数据
        rows = self.driver.find_elements(By.XPATH, '//tr[@class="odd" or @class="even"]')
        for row in rows:
            tds = row.find_elements(By.TAG_NAME, "td")
            if len(tds) >= 14:
                data = [td.text for i, td in enumerate(tds) if i != 3][:14]
                item = {
                    'id': data[0],
                    'code': data[1],
                    'name': data[2],
                    'price': data[3],
                    'change_percent': self.clean_percent(data[4]),
                    'change_amount': data[5],
                    'volume': self.convert_unit(data[6]),
                    'amount': self.convert_unit(data[7]),
                    'amplitude': self.clean_percent(data[8]),
                    'high': data[9],
                    'low': data[10],
                    'open_price': data[11],
                    'close_price': data[12]
                }
                self.save_to_db(item, table_name)
  • scrape_all_boards(self): 爬取所有板块数据的方法。它调用 scrape_board 方法三次,分别爬取沪深A股、上证A股和深证A股的数据。
    def scrape_all_boards(self):
        # 爬取三个板块的数据
        self.scrape_board("hs_a", "quotes_hs_a")
        self.scrape_board("sh_a", "quotes_sh_a")
        self.scrape_board("sz_a", "quotes_sz_a")
  • create_table(self, table_name): 创建数据库表的方法。save_to_db(self, item, table_name): 将数据保存到数据库的方法。

 def create_table(self, table_name):
        # 创建表的SQL语句
        create_table_sql = f"""
            CREATE TABLE IF NOT EXISTS {table_name} (
            # 略
            )
            """
        self.cursor.execute(create_table_sql)
 def save_to_db(self, item, table_name):
        # 插入数据到指定的表中
        sql = f"""
        INSERT INTO {table_name} (id, code, name, price, change_percent, change_amount, volume, amount, amplitude, high, low, open_price, close_price)
        VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """
        self.cursor.execute(sql, (
            item['id'], item['code'], item['name'], item['price'],
            item['change_percent'], item['change_amount'], item['volume'],
            item['amount'], item['amplitude'], item['high'],
            item['low'], item['open_price'], item['close_price']
        ))
        self.connection.commit()

1.1.2实验结果:

  • 将数据爬取并保存到MySQL中三个不同的表格:


1.2实验问题与心得:

1.2.1实验问题及解决方法:

  • 问题1:
    相较于上一次的实验(实验3),这次要求通过selenium方法对相同网页进行信息爬取,区分与抓包的区别
  • 解决方法:
    • Selenium爬取:使用Selenium库模拟浏览器操作,可以执行JavaScript,处理Ajax加载的内容,适合爬取动态生成的数据和交互式网页。
    • 抓包爬取:通过分析网络请求和响应来抓取数据,通常用于处理静态内容,对于动态加载的数据可能无法直接获取。
  • 问题2:
    上述的selenium爬取三个模块的方法使用的是分别调用三次爬取的方法,每爬取一个模块的信息后退出重新爬取,是否可以在一次性多次爬取
  • 解决方法:
    • 循环调用爬取函数:在单个函数中循环调用爬取模块的方法,而不是分开调用,这样可以减少重复代码和启动浏览器的时间。
    • 使用多线程或异步处理:利用Python的多线程或异步IO来同时爬取多个模块,提高效率。
    • 优化等待策略:使用更智能的等待策略,如WebDriverWait,等待所有模块的特定元素加载完成后再进行爬取,而不是等待整个页面加载完成。

1.2.2实验心得:

  • 熟练掌握Selenium:熟悉Selenium的各种方法和属性对于高效定位元素和爬取数据至关重要。
  • 异常处理:在爬虫代码中添加异常处理逻辑,可以确保在遇到错误时程序不会直接崩溃,而是给出错误信息或者进行重试。

二、作业②

要求:

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

输出信息:MYSQL数据库存储和输出格式

Id cCourse cCollege cTeacher cTeam cCount cProcess cBrief
1 Python数据分析与展示 北京理工大学 嵩天 嵩天 470 2020年11月17日 ~ 2020年12月29日 “我们正步入一个数据或许比软件更重要的新时代。——Tim O'Reilly” ……
2 ...... ...... ...... ...... ...... ...... ......

Gitee文件夹链接:https://gitee.com/zheng-bingzhi/2022-level-data-collection/blob/master/实验四/mooc.py

2.1实验代码及结果

2.1.1核心代码:

用户模拟登录界面:

  • 通过 Selenium 打开目标登录页面,等待页面加载。
  • 使用 CSS 选择器定位并点击“登录/注册”按钮,触发登录弹窗。
  • 切换到登录 iframe,并分别输入手机号和密码。
  • 点击“登录”按钮,并切换回主窗口。
driver.get("https://www.icourse163.org")
time.sleep(2)

# 点击“登录/注册”按钮
login_register_button = WebDriverWait(driver, 2).until(
    EC.element_to_be_clickable((By.CSS_SELECTOR, "div._3uWA6[role='button']"))
)
login_register_button.click()

# 切换到 iframe 并输入手机号和密码
iframe = WebDriverWait(driver, 2).until(
    EC.presence_of_element_located((By.CSS_SELECTOR, "iframe[src*='index_dl2_new.html']"))
)
driver.switch_to.frame(iframe)
phone_input = WebDriverWait(driver, 2).until(
    EC.presence_of_element_located((By.ID, "phoneipt"))
)
phone_input.send_keys("19577660828")  # 替换为实际手机号

password_input = WebDriverWait(driver, 2).until(
    EC.presence_of_element_located((By.CLASS_NAME, "j-inputtext"))
)
password_input.send_keys("1314520.abc")  # 替换为实际密码

login_button = WebDriverWait(driver, 5).until(
    EC.element_to_be_clickable((By.ID, "submitBtn"))
)
login_button.click()
driver.switch_to.window(driver.window_handles[-1])  # 切换到新窗口

XPath 定位和点击元素:

  • 在登录后等待并定位“同意”按钮,点击以同意服务条款。
  • 等待“国家精品课”链接加载,点击该链接进入相应课程页面。
# 点击“同意”按钮
agree_button = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.XPATH, '//button[ @class="btn ok"]'))
)
agree_button.click()

# 定位到“国家精品课”链接并点击
national_course_link = WebDriverWait(driver, 10).until(
    EC.element_to_be_clickable((By.XPATH, '//a[@href="https://www.icourse163.org/channel/2001.htm"]'))
)
national_course_link.click()

循环点击课程、数据爬取:

  • 使用循环遍历每个课程项,依次点击以进入课程详情页。
  • 在详情页中提取课程的各类信息(如课程名称、学校、老师、参与人数、时间、课程详情)。
  • 关闭详情页并返回课程列表页面;若为第 5 项或其倍数,点击特定的分页按钮加载更多课程。
for i, course_item in enumerate(course_items):
    course_item.click()
    time.sleep(5)

    new_window_handle = driver.window_handles[-1]
    driver.switch_to.window(new_window_handle)

    cCourse = driver.find_element(By.XPATH, '//span[@class="course-title f-ib f-vam"]').text
    cCollege = driver.find_element(By.XPATH, "//img[@class='u-img']").get_attribute("alt")
    cTeacher = driver.find_element(By.XPATH, '//div[@class="cnt f-fl"]//h3[@class="f-fc3"]').text
    cCount = driver.find_element(By.XPATH, '//span[@class="count"]').text
    cProcess = driver.find_element(By.XPATH, "//div[@class='course-enroll-info_course-info_term-info_term-time']").text
    cBrief = driver.find_element(By.XPATH, "//div[@class='course-heading-intro_intro']").text

    with open(csv_file, mode="a", encoding="utf-8", newline='') as file:
        writer = csv.writer(file)
        writer.writerow([serial_number, cCourse, cCollege, cTeacher, cCount, cProcess, cBrief])

    driver.close()
    driver.switch_to.window(driver.window_handles[-1])
    time.sleep(2)
    
    if (1+i) % 5 == 0:
        special_div = WebDriverWait(driver, 10).until(
            EC.element_to_be_clickable((By.XPATH, "//div[contains(@class, '_2uD4W') and contains(@class, '_2zoND')]"))
        )
        special_div.click()
        time.sleep(2)

写入数据库:

  • 连接数据库
  • 创建表格
  • 整理爬取数据格式,去除多余无效数据
  • 写入数据库
db_connection = mysql.connector.connect(
    host="localhost",       # 数据库地址
    user="root",   # 数据库用户名
    password="123456", # 数据库密码
    database="datacollection_zbz"  # 数据库名
)

# 创建数据库表格
cursor = db_connection.cursor()

# 如果表已经存在,先删除它
cursor.execute("DROP TABLE IF EXISTS course_data")

# 创建表格
create_table_query = """
CREATE TABLE course_data (
...
)
"""
cursor.execute(create_table_query)

# 提取“参与人数”列中的数字
course_data['participants'] = course_data['参与人数'].apply(lambda x: int(re.sub(r'\D', '', str(x))))

# 去掉“开课时间:”部分
course_data['course_time'] = course_data['时间'].apply(lambda x: re.sub(r'开课时间:', '', str(x)))

# 插入数据到MySQL表格中
for index, row in course_data.iterrows():
    insert_query = """
    INSERT INTO course_data (id, course_name, school, teacher, participants, course_time, course_details)
    VALUES (%s, %s, %s, %s, %s, %s, %s)
    """
    cursor.execute(insert_query, (
...
    ))

2.1.2实验结果:

  • 成功将爬取的数据写入数据库:

2.2实验问题及结果:

2.2.1实验问题及解决方法:

  • 问题1:模拟用户登入时无法找到账户密码输入框

  • 解决方法:

    • 在此问题中,首先需要确认是否正确定位到登录框所在的 iframe,在 Selenium 中,操作页面中的 iframe 是常见的障碍。通过 WebDriverWait 等方法确保页面元素已加载完成并切换到正确的 iframe 才能进行输入操作。
      -定位登录框所在的 iframe:确保通过 CSS 选择器或 XPath 定位到正确的登录框;切换到 iframe:使用 driver.switch_to.frame() 方法切换到 iframe 中;确保元素加载完成后再进行操作:使用 WebDriverWait 来等待元素加载完毕。
  • 问题2:点击进入课程后无法爬取数据

  • 解决方法:

    • 因为打开新窗口或新标签页后未正确切换浏览器窗口导致的
    • Selenium 在打开新的页面时需要切换到新的窗口/标签页来进行操作
    • 使用 driver.switch_to.window() 方法切换到新窗口,确保在正确的页面上提取数据
  • 问题3:循环爬取五个课程后无法继续点击进入后续课程爬取数据

  • 解决方法:

    • 在课程总览页面,每五个课程为一批,只有点击下一页按钮 > 后,才会加载更多课程供爬取。
    • Selenium 只能模拟用户在当前可见页面上的点击操作。当页面内容分批加载时,需要点击“下一页”按钮才能加载后续课程。
    • 通过定位 > 按钮并进行点击,可以实现分页加载。

2.2.2实验心得:

  • Selenium 的稳定性与动态页面的互动性: 在动态网页中(例如异步加载内容的网页),Selenium 的操作非常依赖页面加载状态和元素的可见性。因此,我们需要更多地使用 WebDriverWait 和 expected_conditions 来确保每个元素都加载完成并且是可操作的。

  • 处理 iframe: Selenium 在操作 iframe 时必须先切换到相应的框架,否则无法访问框架内的元素。在进行登录操作时,务必确保正确地切换到 iframe 才能找到用户名、密码等输入框。遇到 iframe 问题时,要特别注意页面的切换和元素的定位。

  • 新窗口或标签页的切换: 当用户点击某些链接时,页面会打开一个新的标签页或窗口。在这种情况下,必须切换到新窗口才能继续抓取数据。通过 driver.window_handles 获取窗口句柄并进行切换是非常重要的一步。

分页操作: 对于需要分页加载内容的页面,使用 Selenium 时要明确理解页面的加载逻辑。通过点击“下一页”或类似的按钮才能获取后续数据。在每个批次的数据爬取完后,需要模拟用户点击“下一页”按钮加载新数据。

三、作业③:

要求:

  • 掌握大数据相关服务,熟悉Xshell的使用
  • 完成文档 华为云_大数据实时分析处理实验手册-Flume日志采集实验(部分)v2.docx 中的任务,即为下面5个任务,具体操作见文档。
  • 环境搭建:开通MapReduce服务
  • 实时分析开发实战:
    • 任务一:Python脚本生成测试数据
    • 任务二:配置Kafka
    • 任务三:安装Flume客户端
    • 任务四:配置Flume采集数据

3.1实验关键步骤或结果截图:

3.1.1Python脚本生成测试数据

3.1.2配置Kafka

  • 下载Kafka客户端:
  • 查看下载后文件:


3.1.3安装Flume客户端


3.1.4配置Flume采集数据



3.2实验心得:

  • 在配置Flume以采集数据的过程中,我面临了不少挑战,但这也成为了整个实验中最具教育意义的环节。我掌握了如何依据不同的数据源和目标系统来定制Flume配置,这不仅增强了我对Flume配置文件的掌握,也加深了我对数据流动、处理和传输过程的理解。

  • 通过这一系列的操作,我对大数据的实时分析处理有了更深刻的理解。我意识到,从环境搭建到数据生成,再到数据的采集和传输,每一个环节都是确保大数据项目成功的关键。这些经历不仅提升了我的技术技能,也加深了我对大数据生态系统中各个组件如何协同工作的认识。通过亲身实践,我更加坚信大数据技术在现代数据处理中的核心地位及其巨大的应用潜力。

posted @ 2024-11-15 16:06  郑冰智  阅读(30)  评论(0编辑  收藏  举报