Update on 2018/09/21 最近机房 dalao 爬取了洛谷的全部难度数据(包括主题库、CF、SP、UVa、At),爬取的速度比人手动在题目列表翻页还慢(所以应该不会导致封 IP 吧 qwq),跑了半个多小时。
前言
洛谷于 9 月 23 日加入难易度统计功能,可以在个人主页下方找到
这位 dalao 根据爬取的数据创建了一个数据库,利用这个数据库,我们可以试着统计一下洛谷的做题记录。
就以另一个 dalao 的做题记录进行统计,跑出来的结果是这样的
因为只需要爬取单个用户的主页,所以不会被封 IP(但是如果强行把它魔改成统计多个用户的另说)
准备工作
Python 库
首先需要安装一些必需的库。
爬取页面的 beautifulsoup4
库和解析 HTML 用到的 lxml
库。
这些库都可以通过 pip 来安装。(指令 pip install XXX
)
SQLite3
进行数据库操作需要 SQLite,它可以和 Python 对接(当然也有和其他语言对接的接口,比如 C++ 和 Java)
SQLite 总共只有 2MB 大,把它放到你的硬盘上并添加到环境变量吧。
这样直接在 Python 代码中愉快地 import sqlite3
就好了。
官方下载页传送门
正题
爬取通过题目
洛谷于 9 月 20 日起在用户主页加入混淆题目编号(在浏览器内不会显示但是爬虫可以获取到)
针对这样的反爬虫机制,所以更新了针对混淆题目的过滤机制的代码,这里只提供思路,不提供代码。
[notice]
请大家不要滥用爬虫,爬虫本应该是一个为人服务的合理工具。希望大家能够合理利用爬虫,为自己服务。
[/notice]
首先需要获取用户主页 HTML,然后在里面找出用户做过的题目就行了。
可以强行在爬到的 HTML 代码里用正则表达式匹配(正则表达式已经凉凉了),当然既然能解析 HTML,那一定要解析它来获取啊。
直接找出 div
标签中 class
名为 lg-article am-hide-sm
的部分,然后里面所有的 a
标签都是题目编号。
(现在需要过滤掉 span
标签,有些带有 a
标签的是混淆题目)
所以像这样遍历一遍就能输出该用户 AC 过的题目。(现在同时会输出混淆题目)
反反爬虫
过滤掉 span
标签里的题目。可以考虑先爬取 span
标签内的题目,并存到一个 list (filt
)里。
然后爬取 a
标签内的题目,存到一个 list (pro
)里。使用 remove
函数进行删除操作。
就像这段代码一样。
这样遍历过一遍之后 pro
里就只有正常题目了。
进行数据库查询
数据库查询基本操作
我们使用的数据库中只有一个表(原先本来按题库分类有好几个表的,后来嫌查询起来太麻烦合并成了一个表)
使用 .tables
命令显示表,只有一个叫 QAQ 的表。
让我们以 P1001 为例进行查询。
这个表的两个 column 分别是 ID
和 Dif
查询语句的基本语法就是像上图那样
与 Python 对接
创建数据库连接
进行数据库查询
输出查询结果
进行统计
Python 可以在定义列表时这么操作(如果是 C++ 可以使用 map 映射)
像这样进行输出
完整代码
旧版爬虫,有写爬虫基础的人稍微改一改就能应对反爬机制。更新日志见下方。
Update
添加计算各难度所占百分比和计算权值功能
效果是这样的
具体评级计算的各难度权值表格
Difficulty | Value |
---|
入门难度 | 1 |
普及- | 2 |
普及/提高- | 4 |
普及+/提高 | 8 |
提高+/省选- | 16 |
省选/NOI- | 32 |
NOI/NOI+/CTSC | 64 |
尚无评定 | 0 |
其中“尚无评定”难度权值为 0,因为有很多非洛谷官方题库的题目都是尚无评定难度,这些难度分布差距较大,所以不纳入计算。
Update 2
针对洛谷反爬虫机制增加过滤。
使用原来的代码将会爬出来没有 AC 过的题目并纳入计算。
新版代码会过滤掉那些混淆题目。
Update 3
-
支持中英文 ID 输入和 UID 输入
-
根据通过量绘制饼状图。效果如图
代码及数据库下载
旧版本 (485 KB)
原始版本 (485 KB)