def categoryCatch(request,id): """***抓取所有一级分类和其子分类***""" #--得到当前抓取网站相关信息--# site=SiteInfo.objects.get(id=id) #得到当前抓取的站点信息 log=Log.objects.get(siteId=id) #得到当前抓取站点的日志Log startUrl=site.startUrl #得到抓取的起始页地址 #--开始匹配和抓取--# try: topC=compiledTopPatterns.finditer(getHtml(startUrl)) #调用公共函数catchIter抓取所有一级分类,得到所有一级分类的迭代器 except URLError,e: #如果出现URLError,将错误记录到日志,并返回错误信息和当前事件 urlErrorHandler(log,e) #调用urlErrorHandler函数处理URLError log.currentEvent='Catch Category False' #如果发生异常,则记录事件为'Catch Category False' log.save() #保存log数据 return HttpResponse(log.errorInfo) #返回log信息
def categoryCatch(request,id): """***抓取所有一级分离和其子分类***""" #--得到当前抓取网站相关信息--# site=SiteInfo.objects.get(id=id) #得到当前抓取的站点信息 log=Log.objects.get(siteId=id) #得到当前抓取站点的日志Log startUrl=site.startUrl #得到抓取的起始页地址 #--抓取分类--# try: topC=compiledTopPatterns.finditer(getHtml(startUrl)) #抓取所有一级分类,得到所有一级分类的迭代器 except URLError,e: #如果出现URLError,将错误记录到日志,并返回错误信息和当前事件 urlErrorHandler(log,e) #调用 urlErrorHandler函数处理异常 log.currentEvent='Catch Category' log.save() return HttpResponse(log.errorInfo)
def singleBookSave(subcategory,log,b,itemId): """***单本书函数:单本书籍的抓取、匹配、最后保存到数据库***""" #--得到单本书的信息,并保存到数据库--# imgUrl=getGroup(b,'ImgUrl') #取出封面小图地址 buyUrl=getGroup(b,'Url') #取出购买地址 title=b.group('Title') #取出书名 if title: title=title.decode('GBK') #如果title存在,进行转码 author=b.group('Author') #取出作者 if author: author=author.decode('GBK') #如果author存在,进行转码 publisher=b.group('Publisher') #取出出版社 if publisher: publisher=publisher.decode('GBK') #如果publisher存在,进行转码 date=b.group('Date') #取出出版日期 if date: date=date[10:].decode('GBK') #如果date存在,去掉“出版日期:” 四个字,并转码为UTF-8 price=getGroup(b,'Price') #取出当当价格,并转码 oprice=getGroup(b,'OPrice') #取出原价,并转码 state=getGroup(b,'State') #取出货存状态,并转码 #--如果得到的state为'link_sale',则有货,赋值为1,否则无货,赋值为0--# if state=='link_sale': state=1 else: state=0 #--记录当前事件--# log.currentEvent='Catch bookDetail_2' log.save() detailHtml=getHtml(buyUrl) #得到当前书籍的购买网页数据 try: bookDetail_2=compiledDetailPatterns_2.search(detailHtml) #抓取书的另一部分信息 edition=bookDetail_2.group('Edition')[11:].decode('GBK') #取出版次,去掉“版次:”,并转码 totalPage=bookDetail_2.group('TPage')[11:].decode('GBK') #取出总页数,去掉“页数:”,并转码 format=bookDetail_2.group('Format')[11:].decode('GBK') #取出开本,去掉“开本:”,并转码 isbn=bookDetail_2.group('ISBN')[13:].decode('GBK') #取出ISBN,去掉“ISBN:”,并转码 pack=bookDetail_2.group('Pack')[11:].decode('GBK') #取出装帧,去掉“装帧:”,并转码 bigImgUrl=bookDetail_2.group('BigImgUrl').decode('GBK') #得到封面大图地址,并转码 captionData=compiledCaptionPatterns.search(detailHtml) #抓取内容简介,并转码 if captionData: #如果匹配到简介,则取出 try: caption=captionData.group('Caption').decode('GBK') #对内容简介进行编码转换 except UnicodeDecodeError: #如果转换编码的过程中捕捉到UnicodeDecodeError,将caption赋值为None caption=None else: caption=None #如果没有匹配到简介,则赋值为None except AttributeError: edition='暂无' totalPage='暂无' format='暂无' isbn='暂无' pack='暂无' bigImgUrl='暂无' caption='暂无' #--保存数据到数据库--# bdetail=BookDetail(title=title,buyUrl=buyUrl,price=price,oprice=oprice, state=state,caption=caption,imgUrl=imgUrl,bigImgUrl=bigImgUrl, author=author,publisher=publisher,date=date,edition=edition, totalPage=totalPage,format=format,isbn=isbn,pack=pack, subCategory=subcategory.title,topCategory=subcategory.topcategory.title,siteId=subcategory.siteId) try: bdetail.save() #保存到数据库 except DataError: pass #如果捕捉到DataError,将其忽略,继续抓取 log.breakItemId=itemId #在Log里记录下当前序号 log.errorInfo='No Exception Raise' #书籍保存成功,无异常发生 log.currentEvent='Save Books Success' #当前事件为保存书籍成功 log.save() #保存Log
def bookDetailUpdate(request,id): """***更新书籍: 如果抓取得到的书籍已存在,则跳过; 如果抓取得到的书籍不存在,表示是新书,则将其具体信息保存***""" #--得到上次抓取的断点信息--# log=Log.objects.get(siteId=id) #取出当前抓取网站的Log lastBreakSubId=log.breakSubId #得到上次抓取的断点子分类id lastBreakPageId=log.breakPageId #得到上次抓取的断点分页页码 lastBreakItemId=log.breakItemId #得到上次抓取的分页中的具体断点书籍序号 subcategory=SubCategory.objects.filter(siteId=id,id__gte=lastBreakSubId) #得到该网站下所有id大于等于断点id的子分类(即从上次断点处开始抓取) #--对所有匹配分类进行判断和抓取--# for c in subcategory: #对所有匹配分类进行循环 log.breakSubId=c.id #在日志里记录当前分类id log.breakSubTitle=c.title #在日志里记录当前分类名称 log.save() #保存Log firstUrl=c.url #得到子分类的图书列表地址(第一页) redirectUrl=urlopen(firstUrl).geturl() #得到子分类地址重定向后的地址(当当在这里做了重定向) #--得到总页数--# pageData=catchIter(pagePatterns,getHtml(redirectUrl)) #抓取列表的分页信息 try: for p in pageData: pagenum=p.group('Page') #得到当前子分类的总页数 totalPageNum=int(pagenum) #将字符串转化为整型,用于下面的循环 except NameError: totalPageNum=1 #如果不存在第二页,则总页数为1 #--开始抓取--# if c.id ==lastBreakSubId: #判断当前子分类是否是上次断点子分类 startPage=lastBreakPageId #如果是,则当前分类的起始页从上次断点分页处开始 for i in range(startPage,totalPageNum+1): #对所有匹配分页进行循环 if i==startPage: #判断是否是上次断点分页,如果是,则后面继续判断具体书籍序号 if i==1: url=redirectUrl #如果上次断点分页为第一页,则使用第一页重定向后的地址redirectUrl else: url=getPageUrl(firstUrl,i) #如果 i 不等于1,调用getPageUrl函数获取分页地址 try: bookDetail_1=catchIter(detailPatterns_1,getHtml(url)) #抓取书的部分信息,得到当前页所有书籍的一个迭代器 except URLError,e: #出现URLError异常后的处理 urlErrorHandler(log,e) #调用urlErrorHandler函数处理URLError itemId=0 #给当页具体书籍序号初始化 for b in bookDetail_1: #对当前页的所有书籍进行循环 itemId+=1 #记录下当前书籍序号 if itemId <= lastBreakItemId: #如果序号小于等于上次断点序号,跳过后面的语句 continue else: #如果序号大于上次断点序号,进行正常抓取和保存 itemId+=1 singleBookSave(c,log,b) #执行单本书抓取和保存 else: #如果不是上次断点分页,则执行正常抓取 log.breakPageId=i #在Log里记录下当前分页页码 log.save() #保存到Log url=getPageUrl(firstUrl,i) try: bookDetail_1=catchIter(detailPatterns_1,getHtml(url)) #抓取书的部分信息,得到当前页所有书籍的一个迭代器 except URLError,e: urlErrorHandler(log,e) #调用urlErrorHandler函数处理URLError itemId=0 for b in bookDetail_1: itemId+=1 singleBookSave(c,log,b,itemId) #调用singleBookSave函数完成单本书籍的抓取和保存
def bookDetailCatch(request,id): """抓取书籍的具体信息,包括书名,作者,价格,购买地址等""" #--得到上次抓取的断点信息--# log=Log.objects.get(siteId=id) #取出当前抓取网站的Log lastBreakSubId=log.breakSubId #得到上次抓取的断点子分类id lastBreakPageId=log.breakPageId #得到上次抓取的断点分页页码 lastBreakItemId=log.breakItemId #得到上次抓取的分页中的具体断点书籍序号 subcategory=SubCategory.objects.filter(siteId=id,id__gte=lastBreakSubId) #得到该网站下所有id大于等于断点id的子分类(即从上次断点处开始抓取) errorcode=0 #初始化errorcode #--对所有匹配子分类进行循环、判断、抓取--# for c in subcategory: #对所有匹配分类进行循环 log.breakSubId=c.id #在日志里记录当前分类id log.breakSubTitle=c.title #在日志里记录当前分类名称 log.save() #保存Log firstUrl=c.url #得到子分类的图书列表地址(第一页) redirectUrl=urlopen(firstUrl).geturl() #得到子分类地址重定向后的地址(当当在这里做了重定向) #--得到总页数--# try: pageData=compiledPagePatterns.finditer(getHtml(redirectUrl)) #抓取列表的分页信息 except URLError,e: urlErrorHandler(log,e) #调用urlErrorHandler函数进行Log记录 return HttpResponse('Page Exception Raised: %s' % log.errorInfo) #由于没有抓取到分页信息,停止抓取,返回错误信息 try: for p in pageData: pagenum=p.group('Page') #得到当前子分类的总页数 totalPageNum=int(pagenum) #将字符串转化为整型,用于下面的循环 except NameError: totalPageNum=1 #如果不存在第二页,则总页数为1 #--开始抓取--# if c.id ==lastBreakSubId: #判断当前子分类是否是上次断点子分类 startPage=lastBreakPageId #如果是,则当前分类的起始页从上次断点分页处开始 for i in range(startPage,totalPageNum+1): #对所有匹配分页进行循环 if i==startPage: #判断是否是上次断点分页,如果是,则后面继续判断具体书籍序号 if i==1: url=redirectUrl #如果上次断点分页为第一页,则使用第一页重定向后的地址redirectUrl else: url=getPageUrl(firstUrl,i) #如果 i 不等于1,调用getPageUrl函数获取分页地址 try: bookDetail_1=compiledDetailPatterns_1.finditer(getHtml(url)) #抓取书的部分信息,得到当前页所有书籍的一个迭代器 except URLError,e: #出现URLError异常后的处理 urlErrorHandler(log,e) #调用urlErrorHandler函数处理URLError if errorcode==1: #如果发生异常,使用continue跳过后面的语句,循环到下一页 continue itemId=0 #给当页具体书籍序号初始化 for b in bookDetail_1: #对当前页的所有书籍进行循环 itemId+=1 #记录下当前书籍序号 if itemId <= lastBreakItemId: #如果序号小于等于上次断点序号,跳过后面的语句 continue else: #如果序号大于上次断点序号,进行正常抓取和保存 try: singleBookSave(c,log,b,itemId) #执行单本书抓取和保存 except URLError,e: urlErrorHandler(log,e) if errorcode==1: #如果发生异常,使用continue跳过后面的语句,循环到下一本书 continue log.breakItemId=1 #当某一分页所有的书籍循环完毕后,立即将Log里的breakItemId置为1 log.save() #保存到Log else: #如果不是上次断点分页,则执行正常抓取 log.breakPageId=i #在Log里记录下当前分页页码 log.save() #保存到Log url=getPageUrl(firstUrl,i) try: bookDetail_1=compiledDetailPatterns_1.finditer(getHtml(url)) #抓取书的部分信息,得到当前页所有书籍的一个迭代器 except URLError,e: urlErrorHandler(log,e) #调用urlErrorHandler函数处理URLError if errorcode==1: continue itemId=0 for b in bookDetail_1: itemId+=1 try: singleBookSave(c,log,b,itemId) #调用singleBookSave函数完成单本书籍的抓取和保存 except URLError,e: urlErrorHandler(log,e) if errorcode==1: continue
urlErrorHandler(log,e) if errorcode==1: continue log.breakItemId=1 #当某一分页所有的书籍循环完毕后,立即将Log里的breakItemId置为1 log.save() #保存到Log else: startPage=1 #如果不是上次断点分类,则从第一页开始 for i in range(startPage,totalPageNum+1): log.breakPageId=i log.save() #在Log里记录下当前分页页码 if i==1: url=redirectUrl #如果i为1,则说明为第一页,使用第一页重定向后的地址redirectUrl else: url=getPageUrl(firstUrl,i) try: bookDetail_1=compiledDetailPatterns_1.finditer(getHtml(url)) #抓取书的部分信息,得到当前页下所有书籍的迭代器 except URLError,e: urlErrorHandler(log,e) #调用urlErrorHandler函数处理URLError if errorcode==1: continue itemId=0 for b in bookDetail_1: itemId+=1 try: singleBookSave(c,log,b,itemId) #调用singleBookSave函数完成单本书籍的抓取和保存 except URLError,e: urlErrorHandler(log,e) if errorcode==1: continue log.breakItemId=1 log.save()
def bookDetailCatch(request,id): """***抓取书籍的具体信息,包括书名,作者,价格,购买地址等***""" #--得到上次抓取的断点信息--# log=Log.objects.get(siteId=id) #取出当前抓取网站的Log lastBreakSubId=log.breakSubId #得到上次抓取的断点子分类id lastBreakPageId=log.breakPageId #得到上次抓取的断点分页页码 lastBreakItemId=log.breakItemId #得到上次抓取的分页中的具体断点书籍序号 subcategory=SubCategory.objects.filter(siteId=id,id__gte=lastBreakSubId) #得到该网站下所有id大于等于断点id的子分类(即从上次断点处开始抓取) errorcode=0 #--对所有匹配子分类进行循环、判断、抓取--# for c in subcategory: #对所有匹配分类进行循环 log.breakSubId=c.id #在日志里记录当前分类id log.breakSubTitle=c.title #在日志里记录当前分类名称 log.save() #保存Log firstUrl=c.url #得到子分类的图书列表第一页地址(后面用于分页) #--得到下一页的地址,并以此地址做为分页地址的模板,如果下一页存在,则将页数定为100页,否则,说明只有一页,页数定为1--# try: next=compiledPagePatterns.search(getHtml(firstUrl)) #抓取下一页分页地址 except URLError,e: urlErrorHandler(log,e) #如果出现URLError异常,调用urlErrorHandler函数进行Log记录 return HttpResponse('Page Exception Raised: %s' % log.errorInfo) #由于没有抓取到分页信息,停止抓取,返回错误信息 if next: #如果匹配到下一页 nextUrl=next.group('Next') #得到下一页的地址(是一个相对地址,后面将对这个地址进行转换) totalPageNum=100 #将总页数强制定为100 else: totalPageNum=1 #如果没有匹配到下一页,则总页数为1 #--开始抓取--# if c.id==lastBreakSubId: #判断当前子分类是否是上次断点子分类 startPage=lastBreakPageId #如果当前分类是上次断点分类,则从上次断点分页开始抓取,设置起始页为上次断点页码 for i in range(startPage,totalPageNum+1): #对所有匹配分页进行循环 if i==startPage: #判断是否是上次断点分页,如果是,则后面继续判断具体书籍序号 if i==1: url=firstUrl #如果上次断点分页为第一页,则使用第一页地址firstUrl else: url=getPageUrl(nextUrl,i) #如果 i 不等于1,调用getPageUrl函数获取分页地址 try: htmlData=getHtml(url) #得到当前分页的HTML内容数据 except URLError,e: #捕捉URLError异常 urlErrorHandler(log,e) #如果捕捉到异常,调用urlErrorHandler函数进行Log记录 if errorcode==1: #errocode为1时,说明发生异常,则使用continue跳过本次循环后面的语句,循环到下一页 continue bookinfo=compiledDetailPatterns_1.search(htmlData) #对书籍信息1进行匹配(用于判断该页是否超出分页范围,如果超出,则匹配结果为None) if bookinfo: #如果匹配到书籍信息,说明当前页没有超出页码范围 bookDetail_1=compiledDetailPatterns_1.finditer(htmlData) #对当前页的书籍信息1进行匹配,得到当前页所有书籍的购买地址等信息的一个迭代器 itemId=0 #给当页具体书籍序号初始化 for bd1 in bookDetail_1: #对迭代器进行循环,得到每一本书的数据 itemId+=1 #记录下当前书籍序号 if itemId <= lastBreakItemId: #如果序号小于等于上次断点序号,跳过后面的语句 continue else: #如果序号大于上次断点序号,进行正常抓取和保存 try: singleBookSave(c,log,bd1,itemId) #执行单本书抓取和保存 except URLError,e: urlErrorHandler(log,e) #如果捕捉到异常,调用urlErrorHandler函数进行Log记录 if errorcode==1: #errorcode为1时,说明发生异常,则使用continue跳过本次循环后面的语句,循环到下一页 continue log.breakItemId=1 #当某一分页所有的书籍循环完毕后,立即将Log里的breakItemId置为1 log.save() else: #如果bookinfo为None,说明超出页码范围,立即停止分页循环,进行下一个分类的抓取 break else: #如果不是上次断点分页,则执行正常抓取 log.breakPageId=i #在Log里记录下当前分页页码 log.save() url=getPageUrl(nextUrl,i) #调用getPageUrl函数获取分页地址 try: htmlData=getHtml(url) #得到当前分页的HTML内容数据 except URLError,e: #捕捉URLError异常 urlErrorHandler(log,e) #如果捕捉到异常,调用urlErrorHandler函数进行Log记录 if errorcode==1: #errorcode为1时,说明发生异常,则使用continue跳过本次循环后面的语句,循环到下一页 continue bookinfo=compiledDetailPatterns_1.search(htmlData) #对书籍信息1进行匹配(用于判断该页是否超出分页范围,如果超出,则匹配结果为None) if bookinfo: #如果匹配到书籍信息,说明当前页没有超出页码范围 bookDetail_1=compiledDetailPatterns_1.finditer(htmlData) #对当前页的书籍信息1进行匹配,得到当前页所有书籍的购买地址等信息的一个迭代器 itemId=0 for bd1 in bookDetail_1: #对迭代器进行循环,得到每一本书的数据 itemId+=1 try: singleBookSave(c,log,bd1,itemId) #执行单本书抓取和保存 except URLError,e: urlErrorHandler(log,e) #捕捉到URLError异常后,调用urlErrorHandler函数进行Log记录 if errorcode==1: #errocode为1时,说明发生异常,则使用continue跳过本次循环后面的语句,循环到下一本书 continue log.breakItemId=1 #当某一分页所有的书籍循环完毕后,立即将Log里的breakItemId置为1 log.save()
def singleBookSave(subcategory,log,bd1,itemId): """***单本书函数:单本书籍的抓取、匹配、最后保存到数据库***""" #--预先赋值需要的基本信息,用于后面的if判断--# P='出版社:' E='版本:' D='出版日期:' I='ISBN:' Z='装帧:' F='开本:' TP='页码:' #--获取书籍部分信息--# imgUrl=bd1.group('ImgUrl') #取出封面小图地址 buyUrl=bd1.group('BuyUrl') #取出购买地址 title=bd1.group('Title') #取出图书名称 state=bd1.group('State') #取出货存状态 #--如果得到的state为‘现在有货。’,则给state赋值1,否则为0--# if state=='现在有货。': state=1 else: state=0 #--记录Log--# log.currentEvent='Catch bookDetail_2' #记录当前事件 log.save() detailHtml=getHtml(buyUrl) #得到当前书籍购买地址对应页面的HTML内容 bookDetail_2=compiledDetailPatterns_2.search(detailHtml) #对当前书籍信息2进行匹配 if bookDetail_2: author=bookDetail_2.group('Author') #取出作者 bigImgUrl=bookDetail_2.group('BigImgUrl') #取出封面大图地址 else: author=None bigImgUrl='nothing' opricedata=compiledOpricePatterns.search(detailHtml) #匹配原价 if opricedata: #如果匹配到 oprice=opricedata.group('OPrice') #取出原价 else: #如果没有匹配到 oprice='无' #赋值为‘无’ pricedata=compiledPricePatterns.search(detailHtml) #匹配卓越价(同原价) if pricedata: price=pricedata.group('Price') else: price='无' bookDetail_3=compiledInfoPatterns.finditer(detailHtml) #对书籍基本信息进行匹配,得到所有基本信息的迭代器 dic={} #创建一个字典 for bd3 in bookDetail_3: #对基本信息迭代器进行循环 infoTitle=bd3.group('InfoTitle') info=bd3.group('Info') dic[infoTitle]=info #得到一个包含所有基本信息的字典,后面将取出我们需要的基本信息 publisher=getInfo(P,dic) #调用getInfo函数得到出版社 date=getInfo(D,dic) #调用getInfo函数得到出版日期 edition=getInfo(E,dic) #调用getInfo函数得到版次 isbn=getInfo(I,dic) #调用getInfo函数得到ISBN format=getInfo(F,dic) #调用getInfo函数得到开本 pack=getInfo(Z,dic) #调用getInfo函数得到装帧 totalPage=getInfo(TP,dic) #调用getInfo函数得到总页数 captionData=compiledCaptionPatterns.search(detailHtml) #匹配内容简介 if captionData: #如果匹配成功 caption=captionData.group('Caption') #取出内容简介 else: #如果匹配不成功 caption=None #如果内容简介不存在,caption为None #--保存数据到数据库--# bdetail=BookDetail(title=title,buyUrl=buyUrl,price=price,oprice=oprice, state=state,caption=caption,imgUrl=imgUrl,bigImgUrl=bigImgUrl, author=author,publisher=publisher,date=date,edition=edition, totalPage=totalPage,format=format,isbn=isbn,pack=pack, subCategory=subcategory.title,topCategory=subcategory.topcategory.title,siteId=subcategory.siteId) try: bdetail.save() except (DataError,Warning): pass #---记录Log-# log.breakItemId=itemId #在Log里记录下当前序号 log.errorInfo='No Exception Raise' #书籍保存成功,无异常发生 log.currentEvent='Save Books Success' #当前事件为保存书籍成功 log.save() #保存Log
subTitle=sub.group('SubTitle') #取出子分类名称 if i !=1: #由于这个迭代器的第一个是一级分类名称,所以应该排除在外 sc=SubCategory(title=subTitle,url=subLink,topcategory=tc,siteId=id) #将子分类数据保存到数据库中 sc.save() #--保存成功,将事件记录到日志--# log.errorInfo='No Exception Raise' #保存日志错误信息 log.currentEvent='Save Category Success' #保存当前事件 log.save() #--抓取“进口原版”分类,由于卓越的所有分类的进口原版分类url地址错误,所以要从其他页面抓取--# #进口原版的分类地址# IOUrl='http://www.amazon.cn/s/qid=1261309185/ref=sr_nr_n_49?ie=UTF8&rs=658391051&bbn=658391051&rnid=658391051&rh=n%3A658390051%2Cn%3A!658391051%2Cn%3A2045366051' try: IOData=compiledIOPatterns.finditer(getHtml(IOUrl)) #抓取进口原版分类下的子分类,得到一个子分类的迭代器 except URLError,e: urlErrorHandler(log,e) #调用 urlErrorHandler函数处理异常 log.currentEvent='Catch Category' return HttpResponse(log.errorInfo) tc=TopCategory(title='进口原版',url=IOUrl,siteId=id) #保存‘进口原版’到一级分类数据库中 tc.save() for io in IOData: #对其子分类进行迭代 subLink=io.group('SubLink') #取出进口原版子分类地址 subTitle=io.group('SubTitle') #取出进口原版子分类名称 sc=SubCategory(title=subTitle,url=subLink,topcategory=tc,siteId=id) #将进口原版保存到数据库中 sc.save() #--保存成功,将事件记录到日志--# log.errorInfo='No Exception Raise' #保存日志错误信息 log.currentEvent='Save Category Success' #保存当前事件