数据采集实验作业4

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

点击查看代码
from selenium import webdriver
from selenium.webdriver.chrome.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 mysql.connector
import time


class StockSpider:
    def __init__(self):
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--disable-gpu")
        self.driver = webdriver.Chrome(options=chrome_options)

        # MySQL 连接
        self.db = mysql.connector.connect(
            host="127.0.0.1",
            port="33068",
            user="root",
            password="160127ss",
            database="spydercourse"
        )
        self.cursor = self.db.cursor()

    def setup_db(self):
        # 创建表格
        self.cursor.execute("DROP TABLE IF EXISTS stock")
        self.cursor.execute("""
            CREATE TABLE stock (
                id INT AUTO_INCREMENT PRIMARY KEY,
                bStockNo VARCHAR(50),
                stockname VARCHAR(255),
                lastest_price DECIMAL(10, 2),
                ddf DECIMAL(10, 2),
                dde DECIMAL(10, 2),
                cjl VARCHAR(64),
                cje VARCHAR(64),
                zhenfu DECIMAL(10, 2),
                top DECIMAL(10, 2),
                low DECIMAL(10, 2),
                today DECIMAL(10, 2),
                yestd DECIMAL(10, 2)
            )
        """)

    def close(self):
        self.db.commit()
        self.cursor.close()
        self.db.close()
        self.driver.quit()

    def insert_data(self, data):
        # 插入数据
        sql = """
            INSERT INTO stock (bStockNo, stockname, lastest_price, ddf, dde, cjl, cje, zhenfu, top, low, today, yestd)
            VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
        """
        self.cursor.execute(sql, data)

    def fetch_data(self, url, page_limit=5, current_page=1):
        if current_page > page_limit:
            print(f"Reached page limit of {page_limit} pages for {url}.")
            return  # 达到页面限制后停止递归

        self.driver.get(url)
        WebDriverWait(self.driver, 10).until(
            EC.presence_of_all_elements_located(
                (By.XPATH, "//div[@class='listview full']/table[@id='table_wrapper-table']/tbody/tr"))
        )

        rows = self.driver.find_elements(By.XPATH,
                                         "//div[@class='listview full']/table[@id='table_wrapper-table']/tbody/tr")
        for row in rows:
            try:
                bStockNo = row.find_element(By.XPATH, ".//td[2]/a").text
                stockname = row.find_element(By.XPATH, ".//td[3]/a").text
                lastest_price = float(row.find_element(By.XPATH, ".//td[5]/span").text)

                # 去掉百分号并转换为 float
                ddf = float(row.find_element(By.XPATH, ".//td[6]/span").text.replace('%', ''))
                dde = float(row.find_element(By.XPATH, ".//td[7]/span").text.replace('%', ''))

                cjl = row.find_element(By.XPATH, ".//td[8]").text
                cje = row.find_element(By.XPATH, ".//td[9]").text

                zhenfu = float(row.find_element(By.XPATH, ".//td[10]").text.replace('%', ''))
                top = float(row.find_element(By.XPATH, ".//td[11]/span").text)
                low = float(row.find_element(By.XPATH, ".//td[12]/span").text)
                today = float(row.find_element(By.XPATH, ".//td[13]/span").text)
                yestd = float(row.find_element(By.XPATH, ".//td[14]").text)

                # 插入数据
                self.insert_data(
                    (bStockNo, stockname, lastest_price, ddf, dde, cjl, cje, zhenfu, top, low, today, yestd))
            except Exception as e:
                print("Error fetching row data:", e)
                continue

        # 处理分页
        try:
            next_page = self.driver.find_element(By.XPATH, "//a[@class='next paginate_button']")
            next_page.click()
            time.sleep(2)
            # 递归调用以抓取下一页数据,并将当前页数加1
            self.fetch_data(url, page_limit, current_page + 1)
        except:
            print("No more pages to load.")

    def scrape(self, urls):
        self.setup_db()
        for url in urls:
            self.fetch_data(url)
        self.close()


if __name__ == "__main__":
    urls = [
        "http://quote.eastmoney.com/center/gridlist.html#hs_a_board",  # 沪深A股
        "http://quote.eastmoney.com/center/gridlist.html#sh_a_board",  # 上证A股
        "http://quote.eastmoney.com/center/gridlist.html#sz_a_board"  # 深证A股
    ]
    spider = StockSpider()
    spider.scrape(urls)

运行结果

心得体会
在网页数据抓取过程中,经常会遇到一些网页内容是通过 JavaScript 动态加载的情况。这种情况下,页面在初始加载时并不会包含所有需要抓取的数据,而是通过 JavaScript 在后台异步加载数据。这给数据抓取带来了挑战,因为传统的静态抓取方法(如直接使用 requests 库)在页面加载完成后可能无法获取到动态加载的内容。
为了解决这一问题,可以使用 Selenium WebDriver 提供的 WebDriverWait 和 expected_conditions(简称 EC)模块。这些工具可以帮助我们等待页面中特定元素加载完成并可操作后再进行抓取,从而确保我们能够获取到动态加载的数据。

作业②
实验要求及结果
要求:
熟练掌握 Selenium 查找HTML元素、实现用户模拟登录、爬取Ajax网页数据、等待HTML元素等内容。
使用Selenium框架+MySQL爬取中国mooc网课程资源信息(课程号、课程名称、学校名称、主讲教师、团队成员、参加人数、课程进度、课程简介)
候选网站:中国mooc网:https://www.icourse163.org
输出信息:MYSQL数据库存储和输出格式
代码:

点击查看代码
from selenium.webdriver.common.by import By
from selenium import webdriver
import time
import pymysql
import mysql.connector

# MySQL数据库连接
conn = mysql.connector.connect(
    host="127.0.0.1",
    port="33068",
    user="root",
    password="160127ss",
    database="spydercourse"
)
cursor = conn.cursor()

# 创建MOOC表格
cursor.execute("""
CREATE TABLE IF NOT EXISTS mooc (
    Id VARCHAR(20),
    cCourse VARCHAR(100),
    cCollege VARCHAR(100),
    cTeacher VARCHAR(100),
    cTeam VARCHAR(200),
    cCount INT,
    cProcess VARCHAR(100),
    cBrief TEXT
)
""")
conn.commit()

# 插入数据的SQL语句
sql = """
INSERT INTO mooc (Id, cCourse, cCollege, cTeacher, cTeam, cCount, cProcess, cBrief) 
VALUES (%s, %s, %s, %s, %s, %s, %s, %s)
"""

# 用户登录信息输入
n = 1
user_name = "18150061218"
password = "685332Ss"

# 启动浏览器并打开页面
chrome_options = webdriver.ChromeOptions()
chrome_options.add_argument("--headless")
driver = webdriver.Chrome(options=chrome_options)
driver.maximize_window()
driver.get("https://www.icourse163.org/")

# 点击同意隐私政策
load = driver.find_element(By.XPATH, '//*[@id="app"]/div/div/div[1]/div[3]/div[3]/div')
load.click()
time.sleep(3)

# 切换到登录 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)

# 输入账号密码并登录
driver.find_element(By.XPATH, '/html/body/div[2]/div[2]/div[2]/form/div/div[2]/div[2]/input').send_keys(user_name)
driver.find_element(By.XPATH, '/html/body/div[2]/div[2]/div[2]/form/div/div[4]/div[2]/input[2]').send_keys(password)
driver.find_element(By.XPATH, '/html/body/div[2]/div[2]/div[2]/form/div/div[6]/a').click()

# 等待页面加载完成
time.sleep(5)
driver.switch_to.default_content()  # 切换回默认页面
time.sleep(3)

# 同意隐私政策
driver.find_element(By.XPATH, '//*[@id="privacy-ok"]').click()

# 进入课程页面
driver.find_element(By.XPATH, '/html/body/div[4]/div[2]/div[1]/div/div/div[1]/div[1]/div[1]/span[1]/a').click()
driver.switch_to.window(driver.window_handles[-1])

# 分页循环获取课程数据
for _ in range(2):
    for i in range(5):
        try:
            # 获取每个课程的基本信息
            course_info = driver.find_element(By.XPATH, f'//*[@id="channel-course-list"]/div/div/div[2]/div[1]/div[{i+1}]/div/div[3]/div[1]').text.split("\n")
            driver.find_element(By.XPATH, f'//*[@id="channel-course-list"]/div/div/div[2]/div[1]/div[{i+1}]').click()

            # 切换到新打开的课程页面
            driver.switch_to.window(driver.window_handles[-1])

            # 获取团队成员
            team = driver.find_elements(By.XPATH, '//*[@class="f-fc3"]')
            team_list = [t.text for t in team]
            course_info.append(','.join(team_list))

            # 获取课程人数
            try:
                count = driver.find_element(By.XPATH, '//*[@class="count"]').text
            except:
                count = "已有0人参加"
            course_info.append(count[2:-3])  # 处理人数字段

            # 获取课程时间
            try:

                date = driver.find_element(By.XPATH, '//*[@id="course-enroll-info"]/div/div[1]/div[2]/div/span[2]').text
            except:
                date = "无"
            course_info.append(date)

            # 获取课程简介
            brief = driver.find_element(By.XPATH, '//*[@id="j-rectxt2"]').text
            course_info.append(brief)

            # 插入数据库
            values = (n, course_info[0], course_info[1], course_info[2], course_info[3], course_info[4], course_info[5], course_info[6])
            cursor.execute(sql, values)
            conn.commit()

            # 记录数据并关闭当前标签页
            n += 1
            driver.close()
            driver.switch_to.window(driver.window_handles[-1])  # 切换回主标签页
        except Exception as e:
            print(f"错误:{e}")
            driver.close()
            driver.switch_to.window(driver.window_handles[-1])

    # 点击下一页按钮
    driver.find_element(By.XPATH, '//*[@id="channel-course-list"]/div/div/div[2]/div[2]/div/a[10]').click()
    time.sleep(2)

# 关闭数据库连接
cursor.close()
conn.close()

截图

心得体会
在尝试使用搜索框输入课程关键词进行数据抓取时,可能会遇到一些技术上的挑战,例如动态加载、复杂的 JavaScript 交互或难以定位的元素。这导致我们无法通过简单的搜索操作来获取所需的数据。因此,我决定调整策略,改为直接定位课程元素进行抓取。这种方法的核心思想是绕过搜索框,直接访问课程页面或课程列表,从而简化数据抓取的过程。

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

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

任务二:配置Kafka

任务三: 安装Flume客户端


任务四:配置Flume采集数据

心得体会
通过一系列的实验,我不仅学会了如何在云平台上配置和管理大数据服务,还深入领会了Kafka和Flume在处理大数据时的重要作用,尤其是在实时数据流的采集、传输和分析方面。整个学习过程让我对大数据生态系统有了更全面的了解,特别是如何有效地利用现有工具和云平台资源来实现数据的实时处理与分析。在未来的工作中,我计划继续深入研究和应用这些技术,以应对更加复杂的数据分析任务。

posted @ 2024-11-27 11:09  淋祁  阅读(20)  评论(0编辑  收藏  举报