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

前言

网页分析

  • 按F12查看首页源码,可以看到试卷链接是固定的格式。
    首页源码

  • 随便点了一份试卷,如图:
    试卷示例

  • 按F12看光光,看到虽然右上角写着 不是VIP用户,无法查看答案 ,但是正确答案就写在HTML里(为良心网站点赞):

    • 选择题的正确答案的Class跟其他答案的Class相比多了个xz后缀:
      正确选项的Class跟其他的选项比,多了个xz

    • 填空题的答案就用全透明的字体写在原处:
      填空题的答案用全透明的字体写在原处

    • 显示答案的JS:
      显示答案的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显示答案的,这一招太骚了。
  • 这是我写的第一个爬虫程序,经验不足,在所难免。
最后修改:2019 年 11 月 30 日
Null