首页 > 代码库 > python网页爬虫小项目开发
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\tLOMO\Desktop\excel\%s‘%self.xx,‘utf-8‘) if not os.path.exists(path): os.mkdir(path) filenamea1 = unicode(r‘C:\Users\tLOMO\Desktop\excel\%s\A1.xls‘%self.xx, ‘utf-8‘) # 保存文件 self.wba1.save(filenamea1) filenameb1 = unicode(r‘C:\Users\tLOMO\Desktop\excel\%s\B1.xls‘%self.xx, ‘utf-8‘) # 保存文件 self.wbb1.save(filenameb1) filenamea3 = unicode(r‘C:\Users\tLOMO\Desktop\excel\%s\A3&4.xls‘%self.xx, ‘utf-8‘) # 保存文件 self.wba3.save(filenamea3) filenamex = unicode(r‘C:\Users\tLOMO\Desktop\excel\%s\X.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=http://www.mamicode.com/payload)">(.*?)<‘, 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 = "s\d_" + 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(.*?)s\d_.*?_(.*?)"‘, html, re.S) # 得到综合题干内容 self.TIGANLIST = self.spider5(tempb) # 得对综合题干进行处理,得到题干以及对应的位置 tempa = re.findall(‘s\d_(.*?)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="http://www.mamicode.com/(.*?)">(.*?)</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="http://www.mamicode.com/(.*?)">(.*?)</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题目的选项中可能存在多余的选项(非常少)
格式文档
python网页爬虫小项目开发
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。