• python网页爬虫小项目开发


    这是我最近接的一个小项目,花了是整整四天多时间。

    任务是将http://www.examcoo.com/index/detail/mid/7网站下所有的试卷里的试题全部提取出来,首先按照题型进行分类,接着分析出题目的类型 类别 来源 出题时间等等信息,最终将这些信息转化到excel表格中,excel中的数据有着统一的格式。其中有些信息有关医学,故而需要自行了解。

    由于仅仅是是为了完成最终的任务,故而没有使用什么爬虫框架之类的,也没有使用什么数据库来保存数据,尽量做到快速高效,因为你用的东西越多越容易出错,差错控制也非常麻烦。

    整个任务看似简单,但由于目标网站的试题格式非常不规范,必须有着众多的误差检测和筛选。程序的关键部分都在控制差错。

    程序流程:

    1.由于目标网站有着三级页面,为了控制出错,我是按照一个个二级页面来进行爬去的,当然这些都是程序来自动完成的。

    2.首先提取出二级页面中所有的三级页面,爬取三级页面的所有试题,进行分类汇总,然后写入excel

    3.编写程序将各个类型进行汇总

    4.由于做项目时,项目经理改变了excel的数据结构,故而需要对最终excel的格式进行转化,转变为统一的格式。

    技术点:

    1.试题的解析部分需要自行模拟post请求

    2.python操作excel

    其实这次项目的技术点并没有什么,关键还是在差错控制和大局观,中间由于网站太不规范,我差一点点就要放弃了。

    由于项目的程序实在太多,有近十个,还有众多说明文档,格式文档,这只贴出关键部分:

    main.py

    # -*- coding:utf-8 -*-
    #
    # 题干self.TIGANLIST a=[[选项,----],起始,终止,type,[b],[b],[b]]
    # 题目self.TIMULIST  b=[_,题目,解析,[key,A,B,C,D,E],[c]]
    # 信息变量           c=[self.mc,self.lj,------]
    #
    
    import re, urllib, urllib2, chardet, requests, xlwt, pprint, os, time, chardet
    
    class spiderclass():
        def __init__(self):
            self.pid=''
            self.lurude=['959','1023', '1024', '1025', '1031', '1032', '1033', '1034', '1035', '1036', '1037', '1038', '1039',
                          '957', '958', '960', '961', '963', '965', '966', '968', '969', '970', '971', '972', '973','940',
                         '998', '999', '1000', '1002', '1003', '1008', '1009', '1013', '1014', '1015', '1016', '1021',
                         '1022', '1040', '2535','974', '977', '979', '982', '985', '986', '989', '991', '992', '993', '994',
                         '995', '996', '997','941', '942', '943', '944', '945', '946', '947','949', '952', '953', '954', '955', '956' ]
            self.mainbox6=['963']
            self.solved=[]
            self.passbox=[]
            self.xx=''
            for i in self.mainbox6:
                self.xx=i
                self.excelinit()  # 初始化excel
                self.listinit()  # 初始化列表
                self.tmpinit()  # 初始化时间类型等等相关变量
                try:
                    self.spider0(self.xx)
                    self.writeexcel()
                    self.excelsave()                    #保存excel
                    self.solved.append(self.xx)
                except:
                    print self.xx,' 出错'
                    self.passbox.append([self.xx,self.pid])
                # self.spider0(self.xx)
                # print '二级页面完毕'
                # self.writeexcel()
                # self.excelsave()                    #保存excel
                # self.solved.append(self.xx)
            print self.solved
            print self.passbox
            print '出错二级页面:',self.passbox
    
        def excelinit(self):            #初始化excel
            self.wba1 = xlwt.Workbook(encoding='utf-8')
            self.wbb1 = xlwt.Workbook(encoding='utf-8')
            self.wba3 = xlwt.Workbook(encoding='utf-8')
            self.wbx = xlwt.Workbook(encoding='utf-8')
            self.wsa1 = self.wba1.add_sheet('mysheet')
            self.wsa3 = self.wba3.add_sheet('mysheet')
            self.wsb1 = self.wbb1.add_sheet('mysheet')
            self.wsx = self.wbx.add_sheet('mysheet')
            self.a1 = 0                                #excel中的偏移量
            self.a3 = 0
            self.b1 = 0
            self.x = 0
    
        def listinit(self):                        #初始化各个列表
            self.a1box = []  # 各个excel的数组
            self.a3box = []
            self.b1box = []
            self.xbox = []
    
        def tmpinit(self):                          #初始化时间类型等等相关变量
            self.yt=''              #用途
            self.sj=''              #时间
            self.lb=''              #类别
            self.lx=''              #类型
            self.zk=''              #所属专科
            self.tx=''              #题型
            self.lj=''              #题目路径
            self.mc=''              #试卷名称
            self.dfl=''             #大分类
            self.TIMULIST=[]
            self.TIGANLIST=[]
    
        def excelsave(self):
            path=unicode(r'C:Users	LOMODesktopexcel\%s'%self.xx,'utf-8')
            if not os.path.exists(path):
                os.mkdir(path)
            filenamea1 = unicode(r'C:Users	LOMODesktopexcel\%sA1.xls'%self.xx, 'utf-8')  # 保存文件
            self.wba1.save(filenamea1)
            filenameb1 = unicode(r'C:Users	LOMODesktopexcel\%sB1.xls'%self.xx, 'utf-8')  # 保存文件
            self.wbb1.save(filenameb1)
            filenamea3 = unicode(r'C:Users	LOMODesktopexcel\%sA3&4.xls'%self.xx, 'utf-8')  # 保存文件
            self.wba3.save(filenamea3)
            filenamex = unicode(r'C:Users	LOMODesktopexcel\%sX.xls'%self.xx, 'utf-8')  # 保存文件
            self.wbx.save(filenamex)
    
        def urllink(self, link):  # 网页HTML获取以及编码转换
            while 1:
                try:
                    html_1 = urllib2.urlopen(link, timeout=15).read()
                    break
                except:
                    pass
            encoding_dict = chardet.detect(html_1)
            web_encoding = encoding_dict['encoding']
            if web_encoding == 'utf-8' or web_encoding == 'UTF-8':
                html = html_1
            else:
                html = html_1.decode('gbk', 'ignore').encode('utf-8')
            return html
    
        def spider3(self, string):  # 用于得到答案解析
            try:
                jiexi = re.findall('<div>(.*?)</div><div class="mar', string, re.S)
                return jiexi[0]
            except:
                return u'没有解析'
    
        def postrequest(self, pid, temp1, temp2, tokenpid):  # 模拟post请求
            url = 'http://www.examcoo.com/editor/comment/index'
            payload = {'id': None, 'sdtId': None, 'pid': None, 'p': 1, 'l': 0, 'msgid': 0, 'cmid': 0, 'tid': 0,
                       'verifydtid': 0, 'tokenpid': None}
            payload['id'] = temp1
            payload['stdId'] = temp2
            payload['pid'] = pid
            payload['tokenpid'] = tokenpid
            while 1:
                try:
                    r = requests.post(url, data=payload)
                    break
                except:
                    pass
            return self.spider3(r.text)
    
        def spider4(self, string):  # 得到各个选项及正确答案
            list = ['']
            choicerange = re.findall('radioWrapper(.*?)/div></div', string, re.S)
            if choicerange:
                num = len(choicerange)
                numindex = 65  # 选项A的ascii码
                for i in range(num):
                    choice = []
                    word = chr(numindex)
                    if choicerange[i].find('dijitRadioCheckedDisabled') + 1:
                        list[0] += word
                    select = re.findall('Content">(.*?)<', choicerange[i], re.S)[0]
                    select=select.strip().replace(' ','')
                    choice.append(select)
                    list.append(choice)
                    numindex += 1
            else:
                choicerange = re.findall('checkBoxWrapper(.*?)/div></div', string, re.S)
                if choicerange:
                    num = len(choicerange)
                    numindex = 65  # 选项A的ascii
                    for i in range(num):
                        choice = []
                        word = chr(numindex)
                        if choicerange[i].find('dijitCheckBoxCheckedDisabled') + 1:
                            list[0] += word
                        select = re.findall('Content">(.*?)<', choicerange[i], re.S)[0]
                        select = select.strip().replace(' ', '')
                        choice.append(select)
                        list.append(choice)
                        numindex += 1
            return list
    
        def spider2(self, pid, list, tokenpid):  # 对每一个题目进行分析得到题目以及解析
            length = len(list)
            TIMULIST = []  # 总题目列表
            for i in range(length):
                selection = self.spider4(list[i])  # 得到选项及正确答案
                if selection[0]:
                    TIMU = []  # 单个题目列表
                    question = re.findall('subjectBox">(.*?)<sp', list[i], re.S)[0].replace(' ','').replace('(' ,'').replace(')','').strip() # 得到问题
                    id = re.findall('anchor="(.*?)"', list[i], re.S)[0]  # 得到stdid
                    stdId = "sd_" + id + "_%s" % (str(i + 1))  # 得到id
                    jiexi = self.postrequest(pid, id, stdId, tokenpid).replace('<br>', ' ')  # 得到答案解析
                    TIMU.append(i + 1)   #实际位置
                    TIMU.append(question)
                    TIMU.append(jiexi)
                    TIMU.append(selection)
                    TIMULIST.append(TIMU)
            return TIMULIST
    
        def catchexcept(self, str, string):  # 提取文本并捕获异常
            try:
                return re.findall(str, string, re.S)[0]
            except:
                return ' '
    
        def spider6(self, string):  # 爬取profile中的内容
            list = []
            list.append(self.catchexcept('paperName">(.*?)<', string))
            return list
    
        def spider5(self, tempb):  # 得对综合题干进行处理,得到题干以及对应的位置
            TIGAN = []
            for i in tempb:
                tempc = []
                tigan = re.findall('blockBox.*?>(.*?)</div', i[0], re.S)
                for k in tigan:
                    if k.strip() == ' ':
                        tigan.remove(k)
                    if k.strip() == '<br type="_bogus">':
                        tigan.remove(k)
                for d in range(len(tigan)):
                    tigan[d]=tigan[d].replace(' ',' ')
                point=['~','-','~','—','-','——','一']                    #提取出题干的作用域
                tip=0
                lenght1=len(tigan)
                if lenght1:
                    for n in range(lenght1-1,-1,-1):
                        for b in point:
                            end = re.findall('(d+%s(d+)'%b, tigan[n], re.S)
                            index=n
                            if end:
                                tip=1
                                break
                        if tip:
                            break
                    if not end:
                        for n in range(lenght1 - 1, -1, -1):
                            for b in point:
                                end = re.findall('(d+%s(d+)' % b, tigan[n], re.S)
                                index = n
                                if end:
                                    tip = 1
                                    break
                            if tip:
                                break
                    if not end:                 #如果搜索不到point里的字符则尝试匹配B1类型
                        if len(tigan)>=4:       #如果tiagn的长度大于4,则可能是B1类型
                            if 'A' in tigan[0] and 'B' in tigan[1]:   #尝试匹配B1类型
                                tempc.append(tigan)
                                tempc.append(int(i[1]))
                                tempc.append(None)
                                tempc.append('b1')
                                TIGAN.append(tempc)
                            if 'A' in tigan[1] and 'B' in tigan[2]:   #尝试匹配B1类型
                                tempc.append(tigan[1:])
                                tempc.append(int(i[1]))
                                tempc.append(None)
                                tempc.append('b1')
                                TIGAN.append(tempc)
                    else:                       #正常情况下,则做常规设置
                        for y in range(index,-1,-1):            #去掉题干中无用的信息
                            del tigan[y]
                        if len(tigan)>0:
                            if len(tigan):
                                tempc.append(tigan)
                                tempc.append(int(i[1]))
                                tempc.append(int(end[0]))
                                if len(tigan)>4:
                                    tempc.append('b1')
                                else:
                                    tempc.append('a3')
                                TIGAN.append(tempc)
                            else:
                                tempc.append(tigan)
                                tempc.append(int(i[1]))
                                tempc.append(int(end[0]))
                                tempc.append('wrong')
                        else:
                            tempc.append(tigan)
                            tempc.append(int(i[1]))
                            tempc.append(int(end[0]))
                            tempc.append('wrong')
            for e in range(len(TIGAN)-1):           #设置end为None的题干的end值
                if TIGAN[e][2]==None:
                    TIGAN[e][2]=TIGAN[e+1][1]-1
            try:
                if TIGAN[-1][2]==None:              #若最后一项的end为None则设为500
                    TIGAN[-1][2]=500
            except:
                pass
            return TIGAN
    
        def split1(self):  # 得到A1和A3和B1题型
            deletelist = []
            for i in self.TIGANLIST:
                start = i[1]
                end = i[2]
                type = i[3]
                if i[0] is not []:
                    for j in range(start, end + 1):
                        try:  # 当为最后一项时,用异常捕获
                            i.append(self.TIMULIST[j - 1])
                            deletelist.append(j - 1)
                        except:
                            break
                    if type == 'b1':
                        self.b1box.append(i)
                    elif type=='a3':
                        if i[4][3][2] != ['']:
                            self.a3box.append(i)
                else:
                    self.TIGANLIST.remove(i)
                    for j in range(start, end + 1):
                        deletelist.append(j - 1)
            deletelist.reverse()
            for i in deletelist:
                try:
                    del self.TIMULIST[i]
                except:
                    pass
    
        def split2(self):               #从A1中分离得到A1和X题型
            delete=[]
            for i in range(len(self.TIMULIST)):
                if len(self.TIMULIST[i][3][0])>1:
                    self.xbox.append(self.TIMULIST[i])
                    delete.append(i)
            delete.reverse()
            for i in delete:
                del self.TIMULIST[i]
    
        def split4(self):              #去掉A1中的空项
            deletelist=[]
            for i in range(len(self.TIMULIST)):
                if self.TIMULIST[i][3][2]==['']:
                    deletelist.append(i)
            deletelist.reverse()
            for j in deletelist:
                del self.TIMULIST[j]
            for i in self.TIMULIST:
                self.a1box.append(i)
    
        def split6(self):               #去掉A3&4中的空项
            deletelist = []
            for i in range(len(self.a3box)):
                if self.a3box[i][4][3][2] == ['']:
                    deletelist.append(i)
            deletelist.reverse()
            for j in deletelist:
                del self.a3box[j]
    
        def writea1(self):          #单选
            for i in range(len(self.a1box)):
                self.wsa1.write(self.a1,16,'A1')                    #题型
                self.wsa1.write(self.a1,0,self.a1box[i][1])         #题目
                self.wsa1.write(self.a1,9,self.a1box[i][3][0])      #答案
                self.wsa1.write(self.a1,10,self.a1box[i][2])         #解析
                self.wsa1.write(self.a1, 12, self.a1box[i][4][0])               #时间
                self.wsa1.write(self.a1, 18, self.a1box[i][4][1])               #名称
                self.wsa1.write(self.a1, 17, self.a1box[i][4][2])               #路径
                self.wsa1.write(self.a1,11,self.a1box[i][4][3])                 #用途
                self.wsa1.write(self.a1,13,self.a1box[i][4][4])                 #类别
                self.wsa1.write(self.a1,14,self.a1box[i][4][5])                 #类型
                self.wsa1.write(self.a1, 15, self.a1box[i][4][6])               #专科
                self.wsa1.write(self.a1, 19, self.a1box[i][4][7])               #大分类
                for j in range(len(self.a1box[i][3])-1):
                    self.wsa1.write(self.a1,j+1,self.a1box[i][3][j+1])#选项
                self.a1+=1
    
        def writex(self):           #多选
            for i in range(len(self.xbox)):
                self.wsx.write(self.x, 16, 'X')      #题型
                self.wsx.write(self.x,0,self.xbox[i][1])
                self.wsx.write(self.x,9,self.xbox[i][3][0])
                self.wsx.write(self.x,10,self.xbox[i][2])
                self.wsx.write(self.x, 12, self.xbox[i][4][0])  # 时间
                self.wsx.write(self.x, 18, self.xbox[i][4][1])  # 名称
                self.wsx.write(self.x, 17, self.xbox[i][4][2])  # 路径
                self.wsx.write(self.x, 11, self.xbox[i][4][3])  # 用途
                self.wsx.write(self.x, 13, self.xbox[i][4][4])  # 类别
                self.wsx.write(self.x, 14, self.xbox[i][4][5])  # 类型
                self.wsx.write(self.x, 15, self.xbox[i][4][6])  # 专科
                self.wsx.write(self.x, 19, self.xbox[i][4][7])  # 大分类
                for j in range(len(self.xbox[i][3])-1):
                    self.wsx.write(self.x,j+1,self.xbox[i][3][j+1])
                self.x+=1
    
        def writea3(self):          #题干为情景
            for i in range(len(self.a3box)):
                self.wsa3.write(self.a3, 16, 'A3&4')   # 题型
                for j in range(len(self.a3box[i][0])):
                    self.wsa3.write(self.a3,j,self.a3box[i][0][j])      #题干选项
                self.wsa3.write(self.a3, 12, self.a3box[i][4][4][0])  # 时间
                self.wsa3.write(self.a3, 18, self.a3box[i][4][4][1])  # 名称
                self.wsa3.write(self.a3, 17, self.a3box[i][4][4][2])  # 路径
                self.wsa3.write(self.a3, 11, self.a3box[i][4][4][3])  # 用途
                self.wsa3.write(self.a3, 13, self.a3box[i][4][4][4])  # 类别
                self.wsa3.write(self.a3, 14, self.a3box[i][4][4][5])  # 类型
                self.wsa3.write(self.a3, 15, self.a3box[i][4][4][6])  # 专科
                self.wsa3.write(self.a3, 19, self.a3box[i][4][4][7])  # 大分类
                self.a3+=1
                for k in range(len(self.a3box[i])-4):
                    self.wsa3.write(self.a3 , 1, self.a3box[i][k + 4][1])   #题目
                    self.wsa3.write(self.a3 , 9, self.a3box[i][k + 4][3][0])#答案
                    self.wsa3.write(self.a3 , 10, self.a3box[i][k + 4][2])   #解析
                    tmplist=self.a3box[i][k+4][3]
                    for m in range(len(tmplist)-1):
                        self.wsa3.write(self.a3,m+2,tmplist[m+1])         #选项
                    self.a3+=1
                self.a3+=1
    
        def writeb1(self):          #题干为选项
            for i in range(len(self.b1box)):
                self.wsb1.write(self.b1, 16, 'B1')     # 题型
                for j in range(len(self.b1box[i][0])):
                    self.wsb1.write(self.b1,j,self.b1box[i][0][j])
                self.wsb1.write(self.b1, 12, self.b1box[i][4][4][0])  # 时间
                self.wsb1.write(self.b1, 18, self.b1box[i][4][4][1])  # 名称
                self.wsb1.write(self.b1, 17, self.b1box[i][4][4][2])  # 路径
                self.wsb1.write(self.b1, 11, self.b1box[i][4][4][3])  # 用途
                self.wsb1.write(self.b1, 13, self.b1box[i][4][4][4])  # 类别
                self.wsb1.write(self.b1, 14, self.b1box[i][4][4][5])  # 类型
                self.wsb1.write(self.b1, 15, self.b1box[i][4][4][6])  # 专科
                self.wsb1.write(self.b1, 19, self.b1box[i][4][4][7])  # 大分类
                self.b1+=1
                for k in range(len(self.b1box[i])-4):
                    self.wsb1.write(self.b1 , 1, self.b1box[i][k + 4][1])
                    self.wsb1.write(self.b1 , 9, self.b1box[i][k + 4][3][0])
                    self.wsb1.write(self.b1 , 10, self.b1box[i][k + 4][2])
                    tmplist=self.b1box[i][k+4][3]
                    for m in range(len(tmplist)-1):
                        self.wsb1.write(self.b1,m+2,tmplist[m+1])
                    self.b1+=1
                self.b1+=1
    
        def findpath(self,html):
            one = re.findall('naviState">(.*?)</span></td>', html, re.S)[0]  # 找到试卷路径的大致位置
            two = re.findall('href.*?>(.*?)</a>', one, re.S)
            sjpath = ''
            for i in two[2:]:
                sjpath += '\' + i  # 得到试卷的路径
            return sjpath
    
        def writeexcel(self):           # 将结果分别写入excel
            self.writea1()
            self.writeb1()
            self.writea3()
            self.writex()
    
        def split(self):
            self.split1()         # 得到others和A3和B1题型
            self.split2()                           #从A1中分离得到A1和X题型
            self.split4()                           #去除掉A1中的空项
    
        def finddfl(self):
            dflbox=['主治类','药学类','护理类']
            string=self.mc+self.lj
            for i in dflbox:
                if i in string:
                    self.dfl=i
    
        def findyt(self):
            ytbox=['临床执业医师','临床执业助理医师','中医执业医师','中医执业助理医师','中西医结合执业医师',
                   '中西医结合助理医师','口腔执业医师','口腔执业助理医师','公卫执业医师','公卫执业助理医师',
                   '执业药师资格','初级卫生专业技术资格','中级卫生专业技术资格','内科主治医师','内科主治医师',
                   '外科主治医师','妇产科主治医师','初级药士','初级药师','主管药师','初级中药士','初级中药师',
                   '主管中药师','临床医学检验技士','临床医学检验技师','临床医学检验主管技师','执业护士','初级护师',
                   '主管护师','RDPAC认证']
            string=self.mc+self.lj
            for i in ytbox:
                if i in string:
                    self.yt=i
    
        def findlb(self):
            lbbox=['模拟','真题','全真']
            string = self.mc + self.lj
            if lbbox[0] in string:
                self.lb='模拟题'
            elif lbbox[1] in string:
                self.lb='真题'
            elif lbbox[2] in string:
                self.lb='真题'
            else:
                self.lb='练习题'
    
        def findlx(self):
            lxbox=['基础综合','专业综合','实践综合','中医基础','中医临床医学','西医及临床医学','中西医结合临床医学',
                   '临床综合','药学(中药学)专业知识(一)','药学(中药学)专业知识(二)','药事管理与法规','综合知识与技能(药学、中药学)',
                   '基础知识','相关专业知识','专业知识','专业实践能力','专业实务','RDPAC认证']
            string = self.mc + self.lj
            for i in lxbox:
                if i in string:
                    self.lx = i
    
        def findzk(self):
            zkbox=['外科','中医','口腔','精神病','消化内科','内科护理','护理','内科','神经外科','妇产科','中西医','卫生统计','流行病','中药','药理','心理'
                   ,'微生物','伦理','免疫','生理','病理','职业病','环境卫生','麻醉']
            string = self.mc + self.lj
            for i in zkbox:
                if i in string:
                    self.zk = i+'学'
    
        def findsj(self):
            string = self.mc + self.lj
            time=re.findall('.*?(20[0-9]{2})', string, re.S)
            if len(time):
                self.sj=time[0]
    
        def findtotal(self):
            self.findyt()
            self.findlb()
            self.findlx()
            self.findzk()
            self.findsj()
            self.finddfl()
    
        def spider1(self,pid):  # 对卷面进行解析
            self.tmpinit()      #初始化变量
            self.pid=pid
            link = r'http://www.examcoo.com/editor/do/view/id/%s'%pid
            print '   '+pid+' 三级页面开始处理'
            html = self.urllink(link)  # 得到html代码
            profile = self.spider6(re.findall('profile(.*?)/div></div>', html, re.S)[0])  # 得到profile中的试卷名
            self.mc=profile[0]
            self.lj=self.findpath(html)                  #得到试卷的路径
            self.findtotal()                               #得到试卷用途类别类型等
            tokenpid = re.findall('tokenpid = "(.*?)"', html, re.S)[0]  # 提取出tokenppid
            tempb = re.findall('blockCon(.*?)sd_.*?_(.*?)"', html, re.S)  # 得到综合题干内容
            self.TIGANLIST = self.spider5(tempb)  # 得对综合题干进行处理,得到题干以及对应的位置
            tempa = re.findall('sd_(.*?)id=', html, re.S)  # 提取出所有问题
            self.TIMULIST= self.spider2(pid, tempa, tokenpid)  # 对每一个题目进行分析得到题目以及解析
            for f in range(len(self.TIMULIST)):
                self.TIMULIST[f].append([self.sj,self.mc,self.lj,self.yt,self.lb,self.lx,self.zk,self.dfl])
            self.split()      #分离各个题型
            print '   '+pid+' 三级页面处理完毕'
            return
    
        def spider0(self,id):  # 次级页面主处理函数
            tmp = ''
            pidlist = []
            urlsub='http://www.examcoo.com/paperlist/index/k/%s'%id
            print id+' 二级页面开始处理'
            for i in range(20):
                url=urlsub+'/p/%d'%(i+1)
                html1 = self.urllink(url)
                newpidlist = re.findall('top">(.*?)</td>', html1, re.S)
                if newpidlist[0]==tmp:
                    break
                for j in newpidlist:
                    pidlist.append(j)
                if i==0:
                    tmp=newpidlist[0]
            print pidlist
            a=0
            for i in pidlist:
                a+=1
                if a==30000:
                    break
                else:
                    self.spider1(i)
            print id+' 该二级页面处理完毕'
    
        def spider(self):  # 主页面处理函数
            url = 'http://www.examcoo.com/index/detail/mid/7'
            html = self.urllink(url)
            mainlist = re.findall('catSubBox(.*?)</table></div>', html, re.S)
            a=[]
            for i in mainlist:
                if not i.find('examTableOnly') + 1:  # 若有主题
                    firsttitle = re.findall('examTable">.*?<b>(.*?)</b>', i, re.S)[0]  # 主题名
                    tmp0 = re.findall('course(.*?)</tbody', i, re.S)[0]
                    tmp1 = re.findall('<tr>.*?</tr>', tmp0, re.S)
                    for j in tmp1:
                        secondtitle = re.findall('<span>(.*?)</', j, re.S)[0]  # 二级标题
                        thirdtitle = re.findall('href="(.*?)">(.*?)</a>', j, re.S)  # 三级标题
                        for p in thirdtitle:
                            indexnum=re.findall('k/(.*?)/p',p[0],re.S)[0]
                            a.append(indexnum)
                else:  # 若无主题
                    sublist = re.findall('<td(.*?)</td', i, re.S)
                    titlemain = re.findall('<b>(.*?)</b>', sublist[0], re.S)[0]  # 主标题
                    titlesub = re.findall('href="(.*?)">(.*?)</a>', sublist[1], re.S)  # 副标题
                    for q in titlesub:
                        indexnum=re.findall('k/(.*?)/p',q[0],re.S)[0]
                        a.append(indexnum)
            for s in a:
                self.spider0(s)
            self.writeexcel()                   #将结果分别写入excel
    
    if __name__ == "__main__":
        a = time.time()
        newclass = spiderclass()
        print '耗时', time.time() - a

    说明文档

    最终的文档包含五个文件,其中A1和A2类型的题目放在了一起存于A11final和A12final中,A3和A4类型的题目存于A3文件中
    
    1.试题题型说明
    1.1 A1型题(单句型最佳选择题)(特点:即为单个的单选题,题干为简单的问答)
    细胞坏死的主要形态标志是
    A、线粒体肿胀
    ×B、核碎裂
    C、胞质嗜酸性增强
    D、胞质脂滴增加
    E、自噬泡增多
    1.2 A2型题(病例摘要型最佳选择题)(特点:与A1结构一致,但题干为一案例)
    35岁女性,3周前感冒伴咽痛,2周前已痊愈。近5天颈前疼痛明显,有低热来门诊。查体:T37.8℃,皮肤无汗,甲状腺Ⅱ°大,右叶硬,明显触痛拒按,WBC7.8×109/L.临床诊断最可能是
    A、甲状腺右叶囊肿出血
    B、甲状腺癌伴出血
    C、慢性淋巴性甲状腺炎
    D、急性化脓性甲状腺炎
    ×E、亚急性甲状腺炎
    1.3 A3型题(病例组型最佳选择题)(特点:题干为一个案例,后面跟着多个问题,问题之间没有直接联系)
    (1~3题共用题干)
    35岁男性,因饱餐和饮酒后6小时出现中上腹疼痛,放射至两侧腰部,伴有呕吐2次,为胃内容物,自觉口干,出冷汗。查体:T38℃,四肢厥冷,脉搏116次/分,血压10/6kPa,腹膨胀,全腹弥漫性压痛、反跳痛和肌紧张,肝浊音界存在,移动性浊音阳性,肠鸣音消失。
    1.根据病人的临床表现,不应考虑的诊断是
    A、穿孔性阑尾炎
    B、胃十二指肠溃疡穿孔
    C、绞窄性肠梗阻
    D、急性胰腺炎
    ×E、急性盆腔炎
    2.患者经检查诊断为急性出血坏死性胰腺炎,如行腹腔穿刺,可能抽出液体的颜色是
    A、无色清亮液体
    ×B、棕褐色液体
    C、胆汁样液体
    D、脓性液体
    E、血性液体
    3.治疗方针应是
    A、胃肠减压,密切观察病情变化
    B、中药与针刺
    C、补液抗炎
    ×D、紧急手术
    E、纠正休克后手术
    1.4 A4型题(病例串型最佳选择题)(特点:结构与A3一致,但问题循序渐进,相互关联)
    (1~3题共用题干)
    18岁女性,2年来觉下前牙咬东西无力,近期牙齿感觉松动。检查下前牙松动Ⅰ度。牙龈红肿,有牙石,其它牙龈微肿。
    1.采集病史重点了解
    A、有无外伤史
    ×B、家族史
    C、不良习惯
    D、口腔卫生习惯
    E、有无服药史
    2.重点检查项目是
    A、牙髓活力
    ×B、X线片
    C、松动度
    D、外周血象
    E、牙周附着丧失水平
    3.根据上述检查初步印象为牙周炎,有助于进一步确定诊断的检查是
    A、全身头颅X线
    ×B、龈下菌斑细菌学检查
    C、局部组织病理检查
    D、药物过敏试验
    E、内分泌检查
    1.5 B1型题(又称标准配伍题)(特点:题干为多个选项,后面为多个问题)
    (1~2共用备选答案)
    A、血源性
    B、腺源性
    C、损伤性
    D、牙源性
    E、医源性
    1.新生儿颌骨骨髓炎感染来源多为(A)
    2.化脓性颌骨骨髓炎感染来源多为(D)
    1.6 X型题(特点:即为单个的多选题)
    感染性休克病人治疗原则是
    ×A、及时清除化脓病灶
    ×B、迅速扩充有效血容量
    ×C、应用血管活性药物
    ×D、吸氧×E、维护心肺脑肾等重要脏器功能
    
    
    
    2.其他信息
    大分类=[‘主治类’,’药学类’,’护理类’]
    
    小分类=['临床执业医师','临床执业助理医师','中医执业医师','中医执业助理医师','中西医结合执业医师','中西医结合助理医师','口腔执业医师','口腔执业助理医师','公卫执业医师','公卫执业助理医师','执业药师资格','初级卫生专业技术资格','中级卫生专业技术资格','内科主治医师','内科主治医师','外科主治医师','妇产科主治医师','初级药士','初级药师','主管药师','初级中药士','初级中药师','主管中药师','临床医学检验技士','临床医学检验技师','临床医学检验主管技师','执业护士','初级护师','主管护师','RDPAC认证']
    
    题型编号={A1&2:11 ,  A3&4:12,  B1:13,  X:14}
    
    年份:为出卷时间,由于部分试卷未给出出卷时间,故可能空缺
    
    类别=['模拟','真题',’练习题’]
    
    所属专科=['外科学','中医学','口腔学','精神病学','消化内科学','内科护理学','护理学','内科学','神经外科学','妇产科学','中西医学','卫生统计学','流行病学','中药学','药理学','心理学','微生物学','伦理学','免疫学','生理学','病理学','职业病学','环境卫生学','麻醉学']
    
    类型=['基础综合','专业综合','实践综合','中医基础','中医临床医学','西医及临床医学','中西医结合临床医学','临床综合','药学(中药学)专业知识(一)','药学(中药学)专业知识(二)','药事管理与法规综合知识与技能(药学、中药学)','基础知识','相关专业知识','专业知识','专业实践能力','专业实务','	RDPAC认证']
    
    题目路径:即该试题所对应的试卷在原网站中的索引
    
    所属试卷名:即该试题所在的原试卷的试卷名
    
    ##注释:1.每个题目都有小分类,类型和类别这三种信息,不一定有所属专科类型,时间信息和大分类信息
    
    
    3.可能存在的误差或错误
    总体来说,试题中存在少量不不规范或者错误的地方,在试题被实际使用前最好手动检查一下有没有错误
    3.1 极少数试题中存在无关的信息,例如HTML标签,原网站上的无关信息等
    3.2部分试题由于原网站本身结构的不规范,可能导致试题结构的不规范
    3.3 极少数A3&4和B1题目的选项中可能存在多余的选项(非常少)

    格式文档

  • 相关阅读:
    【微服务架构】SpringCloud组件和概念介绍(一)
    getaddrinfo()详解
    通货膨胀背景下,只能好好搞技术了
    到此为止,重新开始
    二级指针
    一篇关于spice vdagent和利用virtmanager配置spice的文章
    局域网中两台无线路由器联接配置方法图文教程
    ovirt简介
    IIS fastcgi 超时处理
    关于eclipse无法自动编译的问题
  • 原文地址:https://www.cnblogs.com/lomooo/p/6877717.html
Copyright © 2020-2023  润新知