Python爬取信息学在线题库

2019-05-03T19:59:00


最近在研究用Python写爬虫,老师给了我一个网站练手,正好趁热打铁(笑)。

前言

  • 如侵删。

网页分析

  • 按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显示答案的,这一招太骚了。
  • 这是我写的第一个爬虫程序,经验不足,在所难免。
当前页面是本站的「Baidu MIP」版。发表评论请点击:完整版 »