|
本帖最后由 拧发条鸟 于 2016-10-21 22:25 编辑
最近笔者在学习python,以python爬虫作为项目进行实践.
本篇主要学习于Python爬虫实战二之爬取百度贴吧帖子 | 静觅,主体思路大体相同.
爬取代码->正则提取关键信息->写入文件,三大步骤
但是笔者针对程序的的运行效率,编码处理,输入检验,做了适当更改,使得更好的面向客户.
欢迎各位读者大人提出意见和建议.
- #encoding:utf-8
- #v4版本较于v3需要进行数据检测
- #是否是百度网页,是否输入1/0
- import urllib2
- import urllib
- import sys
- import re
- #内容修正包,及url修正包
- class Tool:
- #去除img标签,7位长空格
- removeImg=re.compile(r'<img.*?>| {7}')
- #去除超链接
- removehref=re.compile(r"<a href=.*?>|</a>")
- #换掉换行符\n
- replaceline=re.compile(r"<st>|<div>|</div>|</p>")
- #段落开头换回\n加空两个
- replacePara=re.compile(r"<p.*?>")
- #制表符<td>替换为\t
- replaceTD=re.compile(r"<td>")
- #换行符或双换行符替换为\n
- replaceBR=re.compile(r'<br><br>|<br>')
- #去其他标签
- removeExtraTag=re.compile('<.*?>')
- #去除URL中冗余信息
- removeURL=re.compile('\?.*')
- def replace(self,x):
- x=re.sub(self.removeImg,"",x)
- x=re.sub(self.removehref,"",x)
- x=re.sub(self.replaceline,"\n",x)
- x=re.sub(self.replaceBR,"\n ",x)
- x=re.sub(self.replacePara,"\n ",x)
- x=re.sub(self.replaceTD,"\t",x)
- x=re.sub(self.removeExtraTag,"",x)
- #strip()将前后多余内容删除
- return x.strip()
- def cheakURL(self,x):
- x=re.sub(self.removeURL,'',x)
- return x.strip()
- #百度爬虫类
- class Spider_Baidu:
- #初始参数
- def __init__(self,baseurl,see_lz=1,tag=1):
- self.tag=tag#是否要楼
- self.defualtname="百度贴子"#默认名称
- self.file=None#文件
- self.see_lz=see_lz#是否看楼主
- self.baseURL=baseurl
- self.tool=Tool()
- self.floor=1
- #获取源代码,返回源代码
- def getPage(self,index):
- url = self.tool.cheakURL(self.baseURL)+ "?see_lz=" + str(self.see_lz) + "&pn=" + str(index)
- request = urllib2.Request(url)
- try:
- response = urllib2.urlopen(request)
- pagecode = response.read().decode("utf-8")
- return pagecode
- except urllib2.URLError,e:
- print u"连接失败,失败原因为",e.reason
- return None
- #获取总页数,
- def getPageNum(self,pagecode=None):
- if not pagecode:pagecode=self.getPage(1)
- if not pagecode:return None#如果读取失败返回None
- pattern=re.compile(r'''<span class="red">(.*?)<''',re.S)
- pagenum=re.findall(pattern,pagecode)
- if pagenum:return pagenum[0]
- else:return None
- #获取帖子标题
- def getTitle(self,pagecode=None):
- if not pagecode:pagecode=self.getPage(1)
- if not pagecode:return None
- pattern = re.compile(r'''<h3 class="core_title_txt.*?>(.*?)</h3>''', re.S)
- headline = re.findall(pattern, pagecode)
- if headline:
- return headline[0]
- else:
- return None
- #获取正文内容
- def getContent(self,pagecode):
- pattern = re.compile(r'''<div id="post_content_.*?>(.*?)</div>''', re.S)
- items = re.findall(pattern, pagecode)
- content=[]
- for item in items:
- content.append("\n"+self.tool.replace(item)+"\n")
- if content:return content
- else:return None
- #打开文件
- def opentxt(self,title=None):
- if not title: title = self.getTitle()
- if title:self.file=open(title+".txt",'w+')
- else:self.file=open(self.defualtname+".txt",'w+')
- #写入文件,如果要设计写入是一个单纯的函数,那么应该将floor定义在函数之外
- def txtwrite(self,contends):
- # floor=1
- if self.tag:
- floorlLine = '\n' + str(self.floor)+'楼' + \
- u"---------------" \
- u"----------------" \
- u"-----------------" \
- u"--------------------" \
- u"---------------------\n"
- self.floor+=1
- self.file.write(floorlLine)
- self.file.write(contends)
- return True
- #开始函数
- def start(self):
- indexpage=self.getPage(1)
- pageNum=self.getPageNum(indexpage)
- title=self.getTitle(indexpage)
- if pageNum == None:
- print "URL已失效,请重试"
- return None
- self.opentxt(title)
- try:
- print u"该帖子共" + pageNum + u"页"
- for i in range(1,int(pageNum)+1):
- print u"正在写入第" + str(i) + u"页数据"
- code=self.getPage(i)
- content=self.getContent(code)
- for item in content:
- self.txtwrite(item)
- #出现写入异常
- except IOError,e:
- print u"写入异常"+e.message
- finally:
- print u"写入完成"
- #输入数据类
- class Inputdata:
- baseurl=None
- seezl=None
- floorTag=None
- baidu=re.compile(r"tieba.baidu.com/p")
- def datainput(self):
- print u"请输入帖子网址"
- self.baseurl =raw_input()
- while not re.search(self.baidu,self.baseurl):
- print u"非百度贴吧,请再次输入"
- self.baseurl = raw_input()
- self.seelz = raw_input(u"是否只获取楼主发言,是输入1,不是输入0\n")
- while self.seelz!="1" and self.seelz!="0":self.seelz = raw_input(u"请输入0或1\n")
- self.floorTag = raw_input(u"是否写入楼层信息,是输入1,否输入0\n")
- while self.floorTag!="1" and self.floorTag!="0":self.floorTag = raw_input(u"请输入0或1\n")
- import sys
- import time
- reload(sys)
- sys.setdefaultencoding('utf-8')#处理转码问题
- data=Inputdata()
- data.datainput()
- print data.baseurl,data.seelz,data.floorTag
- spider=Spider_Baidu(data.baseurl,data.seelz,data.floorTag)
- start=time.clock()#计算爬取所用时间
- spider.start()
- end=time.clock()
- print u"用时:%f s"%(end-start)
- raw_input(u"按任意键退出")
- exit(0)
复制代码
|
|