Python分析 oj 网的题目难度和通过率的关系
本着做题的心态,上了东莞理工学院的 oj 网;看了一下题目不想动手,在选择难度的时候发现有些通过率和难度可能存在着某些关系,于是决定爬下这些数据简单查看一下是否存在关系。
一、新建项目
我是用 scrapy 框架爬取的(因为刚学没多久,顺便练练手)。首先,先新建 project (下载 scarpy 部分已省略),在控制台输入 scrapy startproject onlinejudge(其中, onlinejudge为项目名称),敲击回车键新建项目完成。
二、明确目的
在动手写代码之前,先分析一下网页结构。网站是通过动态加载的,数据通过 json 文件加载。
1、明确要爬取的目标: http://oj.dgut.edu.cn/problems 网站里的题目,难度,提交量,通过率。在查找 json 的时候发现只有通过数,那么通过率就要自己计算。
2、打开 onlinejudge 目录下的 items.py 写下如下代码:
class onlinejudgeitem(scrapy.item): id = scrapy.field() # 题目编号 title = scrapy.field() # 标题 difficulty = scrapy.field() # 难度 submissionno = scrapy.field() # 提交量 acceptedno = scrapy.field() # 正确数 passingrate = scrapy.field() # 正确率
三、制作爬虫
1、在当前目录下输入命令:scrapy genspider oj "oj.dgut.edu.cn" (其中 oj 是爬虫的名字,"oj.dgut.edu.cn"算是一个约束,规定一个域名)
2、打开 onlinejudge/spiders 下的 ojspider.py ,增加或修改代码为:
import scrapy import json from onlinejudge.items import onlinejudgeitem class ojspider(scrapy.spider): name = 'oj' # 爬虫的名字 allowed_domains = ['oj.dgut.edu.cn'] # 域名范围 offset = 0 url = 'http://oj.dgut.edu.cn/api/xproblem/?limit=20&offset=' start_urls = [url + str(offset)] # 爬取的url元祖/列表 def parse(self, response): data = json.loads(response.text)['data']['results'] if len(data): for i in range(len(data)): submissionno = data[i]['submission_number'] acceptedno = data[i]['accepted_number'] try: passingrate = round((int(acceptedno)/int(submissionno)) * 100, 2) except zerodivisionerror as e: passingrate = 0 strpr = str(passingrate) + "%" item = onlinejudgeitem() item['id'] = data[i]['_id'] item['title'] = data[i]['title'] item['difficulty'] = data[i]['difficulty'] item['submissionno'] = submissionno item['acceptedno'] = acceptedno item['passingrate'] = strpr yield item print(i) self.offset += 20 yield scrapy.request(self.url + str(self.offset), callback=self.parse)
四、存储数据
1、打算将数据存储为 excel 文档,要先安装 openpyxl 模块,通过 pip install openpyxl 下载。
2、下载完成后,在 pipelines.py 中写入如下代码
from openpyxl import workbook class onlinejudgepipeline(object): def __init__(self): self.wb = workbook() self.ws = self.wb.active # 激活工作簿 self.ws.append(['编号', '标题', '难度', '提交量', '正确数', '正确率']) # 设置表头 def process_item(self, item, spider): line = [item['id'], item['title'], item['difficulty'], item['submissionno'], item['acceptedno'], item['passingrate']] self.ws.append(line) self.wb.save('oj.xlsx') return item
五、设置 settings.py
修改并增加代码:
log_file = "oj.log" robotstxt_obey = true item_pipelines = { 'onlinejudge.pipelines.onlinejudgepipeline': 300, }
六、运行爬虫
在当前目录下新建一个 main.py 并写下如下代码
from scrapy import cmdline cmdline.execute("scrapy crawl oj".split())
然后运行 main.py 文件。
于是,想要的数据就被爬下来了
七、分析数据
分析数据之前,先安装好 numpy,pandas,matplotlib,xlrd。
import pandas as pd import xlrd data = pd.read_excel("../onlinejudge/onlinejudge/oj.xlsx") data.describe()
data = data.set_index('编号')
data.head()
from matplotlib import pyplot as plt import matplotlib.style as psl %matplotlib inline psl.use('seaborn-colorblind') # 设置图表风格 plt.rcparams['font.sans-serif']=['simhei'] #用来正常显示中文标签
查看题目各难度的数目:
level_values = data['难度'].values difficulties = { '简单': 0, '中等': 0, '困难': 0 } for value in level_values: if value == '简单': difficulties['简单'] += 1 elif value == '中等': difficulties['中等'] += 1 else: difficulties['困难'] += 1 level = pd.series(difficulties) print(level) level.plot(kind = 'bar', figsize=(6, 7)) plt.grid(axis='y')
验证正确率与难度直接是否存在关系:
import numpy as np relation = data[['难度', '正确率']] rate_values = relation['正确率'].values fig, axes = plt.subplots(figsize=(15, 6)) axes.scatter(rate_values, level_values) plt.grid(axis='x') plt.xticks(np.arange(0, 1, 0.05)) plt.xlabel('正确率') plt.ylabel('难度')
根据表格显示,题目难度跟正确率是存在一定关系的(我想的没有错哈哈哈)。
上一篇: VUE中v-on:click事件中获取当前dom元素
下一篇: python学习的准备工作