最近在研究用Python写爬虫,老师给了我一个网站练手,正好趁热打铁(笑)。
前言
- 本项目开源: GitHub
- 题库版权归属 http://lib.nbdp.net 所有,本文只做学习交流之用。
- 如侵删。
网页分析
-
按F12查看首页源码,可以看到试卷链接是固定的格式。
-
随便点了一份试卷,如图:
-
按F12看光光,看到虽然右上角写着
不是VIP用户,无法查看答案
,但是正确答案就写在HTML里(为良心网站点赞):-
选择题的正确答案的Class跟其他答案的Class相比多了个
xz
后缀:
-
填空题的答案就用全透明的字体写在原处:
-
显示答案的JS:
-
开工
仅贴出关键代码,完整代码请移步GitHub
-
我使用的环境:
-
Python3.6
-
beautifulsoup4==4.7.1
-
bs4==0.0.1
-
lxml==4.3.3
-
requests==2.21.0
-
xlwt==1.3.0
-
首先使用requests获取HTML源码
import requests …… for i in rang(1,100,1): s=requests.session()url='http://lib.nbdp.net/paper/%d.html' % j html=s.get(url).content html=str(html,encoding='utf-8',errors='ignore')
实测有一份试卷中出现了特殊符号,会导致错误,所以加了一句话重新编码并忽略错误。
-
使用BeautifulSoup解析HTML
from bs4 import BeautifulSoup …… def download_exam(): …… soup = BeautifulSoup(html,'lxml') exams=soup.find_all(name='div',attrs={'s':'math3'}) for x in exams: out=analyzesoup(x) exam.append(out) ……
def analyzesoup(soupobj:bs4.element.NavigableString): def notNone(obj): if obj is None: return(False) return(True) result=soupobj.find(name='p',attrs={'class':'pt1'})#题干 if notNone(result): tigan=result.get_text().strip() result=soupobj.find(name='li')#如果是选择题 if notNone(result): xuanxiang=[] for i in soupobj.find_all(name='li'): xuanxiang.append(i.get_text()) result=soupobj.find(attrs={'class':'col-md-3 column xz'}) if notNone(result): daan=result.get_text() else: daan='未找到答案' out={'tg':tigan,'xx':xuanxiang,'da':daan} return(out) ……
-
使用xlwt将题目写入xls
import xlwt …… def download_exam(): workbook = xlwt.Workbook(encoding = 'utf-8') for j in range(1,102,1): title=str(j)+soup.title.get_text() worksheet = workbook.add_sheet(title) …… sheetwriter(exam,worksheet) workbook.save('dump.xls')
def sheetwriter(list,sheetobj): …… _row=1 for item in list: …… if 'xx' in item:#选择题 sheetobj.write(_row,1, label =item['tg']) sheetobj.write(_row,0, label =item['da']) col=2 for i in item['xx']: sheetobj.write(_row,col, label =i) col+=1 _row+=1 continue if 'dm' in item:#填空题 lines=item['tg'].splitlines(False) _row+=1 for line in lines: sheetobj.write(_row,1, label =line) _row+=1 lines=item['dm'].splitlines(False) for line in lines: sheetobj.write(_row,1, label =line) _row+=1 continue ……
-
差不多完成了,测试一下
-
大概1分钟即可下载完所有题目
-
下载的题目:
-
选择题和简答题的答案写在A列,默认宽度为0(隐藏)
-
填空题和简答题的答案会出现在原位 (
太难提取了)
后记
- 信息学竞赛题库的题库结构很简单,很容易解析,而且完全公开,不用处理cookies,非常适合练手。
- 头一回见把答案写在前端,然后在前端用js显示答案的,这一招太骚了。
- 这是我写的第一个爬虫程序,经验不足,在所难免。
本文链接:https://blog.chrxw.com/archives/2019/05/03/229.html
转载请保留本文链接,谢谢