翼度科技»论坛 编程开发 python 查看内容

Python数据爬取处理可视化,手把手全流程教学

5

主题

5

帖子

15

积分

新手上路

Rank: 1

积分
15
这篇博客中,选取openjudge网站上“百练”小组中的用户答题数据,作为材料进行教学

目录

网站地址:http://bailian.openjudge.cn/

使用到的Python包:requests、pandas、re、BeautifulSoup、time、matplotlib、seaborn



爬取主页面内容

使用requests库,来请求主界面的内容
  1. import requests  # 导入requests库以便进行HTTP请求
  2. # 定义目标URL,指向需要获取内容的网页
  3. url = "http://bailian.openjudge.cn/"
  4. # 发送GET请求到指定的URL,并将响应保存到response变量中
  5. response = requests.get(url)
  6. # 初始化一个变量,用于保存HTML内容,默认为None
  7. html_context_save = None
  8. # 检查HTTP响应的状态码,以确定请求是否成功
  9. if response.status_code == 200:
  10.     # 如果状态码为200,表示请求成功
  11.     html_content = response.text  # 获取响应的HTML内容
  12.     html_context_save = html_content  # 保存HTML内容到变量
  13.     print(html_content)  # 打印HTML内容以供查看
  14. else:
  15.     # 如果状态码不为200,表示请求失败
  16.     print("failed to receive the context")  # 输出失败信息
复制代码
输出结果:拿到了主页面的HTML内容




主页面内容提取

F12进入控制台,在元素里找到“练习”,然后复制路径,得到
document.querySelector("#main > div.main-content > ul > li > h3 > a"),为我们所需要的子页面位置

提取子网页地址:
  1. from bs4 import BeautifulSoup  # 导入BeautifulSoup库用于解析HTML文档
  2. # 使用 BeautifulSoup 库解析 HTML 内容,将其存储在 soup 变量中
  3. soup = BeautifulSoup(html_context_save, 'html.parser')  # 传入HTML内容和解析器类型
  4. # 查找所有具有类名为 "current-contest label" 的HTML元素,并将结果存储在 contests 列表中
  5. contests = soup.find_all(class_="current-contest label")  # 返回一个符合条件的标签列表
  6. import pandas as pd  # 导入pandas库用于数据处理和存储
  7. # 创建一个列表来保存未结束的比赛信息
  8. data = []
  9. # 遍历每个比赛上下文以获取比赛信息
  10. for context in contests:
  11.     # 获取比赛标题,提取h3标签中的文本,并去除多余的空白符
  12.     h3_text = context.find('h3').get_text(strip=True)
  13.     # 查找h3标签下的锚标签(a)并提取其链接和文本
  14.     a_tag = context.find('a')  # 查找第一个<a>标签
  15.     a_href = a_tag['href'] if a_tag else None  # 若存在a_tag,提取其href属性
  16.     a_text = a_tag.get_text(strip=True) if a_tag else None  # 若存在a_tag,提取其文本内容
  17.     # 将比赛信息添加到列表中,用字典格式存储标题和链接
  18.     data.append({
  19.         '标题': a_text,  # 比赛标题
  20.         '链接': f"http://bailian.openjudge.cn{a_href}",  # 完整链接,结合基础URL
  21.     })
  22. # 将数据保存为DataFrame,以便于后续的操作和展示
  23. df = pd.DataFrame(data)
  24. # 输出DataFrame,显示所有未结束的比赛信息
  25. print(df)
复制代码
获得了子网页的地址:




需求数据爬取

进入子网页,点击“状态”,看到上方网站页面多出了“status/”内容,内部的内容为我们需要的数据,可以看到关云长,赵子龙等同学都在提交作业。
在这里我们提取前67页数据作为数据分析的素材。
爬取内容存放在openjudge_data.csv文件

[code]import requests  # 导入请求库,用于发送HTTP请求from bs4 import BeautifulSoup  # 导入BeautifulSoup库,用于解析HTML文档import pandas as pd  # 导入Pandas库,用于数据处理和保存import time  # 导入时间库,用于延迟请求# 定义函数从指定的链接和页码获取数据def fetch_data(contest_url, page_number):    try:        # 发送GET请求,并设置请求参数为页码        response = requests.get(contest_url, params={'page': page_number}, timeout=10)        response.raise_for_status()  # 检查请求是否成功        return response.text  # 返回页面的HTML文本    except Exception as e:        # 如果请求失败,输出错误信息        print(f"Error accessing {contest_url}?page={page_number}: {e}")        return None  # 返回None表示获取数据失败# 定义函数从HTML页面中解析所需的数据def parse_page(html, row_title):    soup = BeautifulSoup(html, 'html.parser')  # 解析HTML文档    problem_status_table = soup.find(id='problemStatus')  # 找到状态表格    if not problem_status_table:        return []  # 如果没有找到表格,返回空列表    rows = problem_status_table.find_all('tr')[1:]  # 获取所有表格行,跳过表头    status_data = []  # 用于保存当前页面的状态数据    for tr in rows:  # 遍历每一行数据        # 提取每列的数据并去除多余空白        submit_user = tr.find('td', class_='submit-user').text.strip()        course_class = tr.find('td', class_='className').text.strip()        problem_title = tr.find('td', class_='title').text.strip()        result = tr.find('td', class_='result').text.strip()        memory = tr.find('td', class_='memory').text.strip()        spending_time = tr.find('td', class_='spending-time').text.strip()        code_length = tr.find('td', class_='code-length').text.strip()        language = tr.find('td', class_='language').text.strip()        # 提取提交时间的绝对和相对格式        date_element = tr.find('td', class_='date').find('abbr')        absolute_time = date_element['title'] if date_element and 'title' in date_element.attrs else None        relative_time = date_element.get_text(strip=True) if date_element else None        # 将每次提交的数据添加到列表中        status_data.append({            '提交人': submit_user,            '班级': course_class,            '题目': problem_title,            '结果': result,            '内存': memory,            '时间': spending_time,            '代码长度': code_length,            '语言': language,            '提交时间(相对)': relative_time,            '提交时间(绝对)': absolute_time,            '标题': row_title  # 将标题信息也存入数据中        })    return status_data  # 返回解析后数据的列表# 用于存储所有抓取到的结果all_status_data = []# 假设 df 已经被定义,并包含所有比赛的链接和标题for index, row in df.iterrows():    contest_url = row['链接'] + 'status/'  # 生成当前比赛的状态页面链接    page_number = 1  # 初始化当前页码    previous_data = None  # 存放上一次抓取的数据,用于比较    while page_number

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x

举报 回复 使用道具