从无到有的“糗事百科”分析
1,麻雀虽小,五脏俱全:
从简单的爬取数据到可视化分析,不仅实践中掌握发现学习Python的乐趣与价值,也在过程中掌握 数据获取,数据清新,数据可视化的整个流程。可谓是“麻雀虽小,五脏俱全“ 。
2,知其然,也知所以然:
从无到有的“糗事百科”分析:利用程序伪造用户浏览器的上下文信息,访问特定的地址,发送请求,接受请求的数据(多为html格式的文本)。
解读文本规则,找到自己想要的数据,利用正则洗出自己想要的数据,存储到文件或数据表中。后续我们可以对存在的数据文件进行一下统计描述,让数据映射为图表。用图说话,胜过万语千言。
环境说明:依赖是Python2
抓取页面:糗事百科 24小时爆笑笑话大全 (页面结构可能变了)
抓取字段:用户昵称,性别,年龄,糗事内容,是否有图,点赞数,喜欢数。
3,我们认识了:糗事百科:
写糗事百科的男性占比高于女性 年龄段集中分布在20到30岁 喜欢写小段子,不喜欢发图片 一入糗百深似海,从此节操为路人
#encoding:utf-8__author__ = 'herain'import sysimport urllibimport urllib2import codecsimport reimport threadimport time#糗事百科爬虫class BaikeCrawler: #init mothed def __init__(self): self.pageNum = 1 self.user_agent = '''Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36''' #init headers self.headers = {'User-Agent': self.user_agent} #save msg for page self.stories = [] #program on-off self.enable = False self.__out_file = codecs.open("qiuxi24_data",'w','utf-8') #afferent pageNum def forCrawler(self, pageNum): try: url ='http://www.qiushibaike.com/hot/page/' + str(pageNum) request = urllib2.Request(url, headers = self.headers) #use urlopen get the html code response = urllib2.urlopen(request) pageHtmlCode = response.read().decode('utf-8') return pageHtmlCode except urllib2.URLError, e: if hasattr(e, 'reason'): print u"链接糗事百科失败,错误原因",e.reason return None
def clearHtmlTag(self,ctx): pat = re.compile(r"<[^>]+>|\s",re.S) return str(pat.sub('',ctx)).encode('utf-8') def clearOtherChar(self, ctx): #处理非中文和英文字符 pat = re.compile(r"<[^>]+>|\s",re.S) return str(pat.sub('',ctx)).encode('utf-8')
def write_line(self, datalist): div = '\001' res = div.join("%s"%str(i).encode('utf-8') for i in datalist) res = "%s\n"%(res) self.__out_file.writelines(res)
def backPageItems(self,pageNum): pageHtmlCode = self.forCrawler(pageNum) if not pageHtmlCode: return None pageStories = [] pattern =re.compile('''<div class="author clearfix">.*?href.*?<img src.*?title=.*?<h2>(.*?)</h2>.*? <div class="articleGender(.*?)">(.*?)</div>.*?<div class="content">.*?<span>(.*?)</span>.*?</div> .*?</a>(.*?)<div class="stats">.*? <i class="number">(.*?)</i>.*?class="stats-comments".*?<i class="number">(.*?)</i>''',re.S) items = re.findall(pattern,pageHtmlCode) for item in items: name = str(item[0]).encode('utf-8') sex = str(('男性' if item[1].strip()=='manIcon' else '女性')).encode('utf-8') age = str(item[2]).encode('utf-8') ctx = self.clearHtmlTag(item[3]) ishaveImg = str(('有' if item[4].strip() else '无')).encode('utf-8') likeNum = str(item[5]).encode('utf-8') comments = str(item[6]).encode('utf-8') #print '用户名:',name,'性别:',sex,'年龄:',age, '\n内容:',ctx, '\n是否有图:' ,ishaveImg,'\n点赞数:' ,likeNum, '评论数:',comments ,'\n\n' self.write_line((name,sex,age,ctx,ishaveImg,likeNum,comments)) return pageStories def loadPage(self): if self.enable == True: if len(self.stories) < 2: pageStories = self.backPageItems(self.pageNum) if pageStories: self.stories.append(pageStories) self.pageNum += 1
def getOneStory(self, pageStories, page): for story in pageStories: input = raw_input() self.loadPage() if input == 'Q': self.enable = False return print '''第%d页\t用户名:%s性别:%s\年龄:%s\t内容:%s\t是否有图:%s\t点赞数:%s \t评论数:%s'''%(page,story[0],story[1],story[2],story[3],story[4],story[5],story[6])
#start mothed def start(self): print u"正在读取糗事百科,按回车查看新段子,Q退出" self.enable = True self.loadPage() nowPage = 0; while self.enable: if len(self.stories)>0: pageStories = self.stories[0] nowPage += 1 del self.stories[0] self.getOneStory(pageStories,nowPage)
if __name__ == "__main__": baike = BaikeCrawler() #baike.start() #该方法启动阅读模式 user_define = raw_input('n,m从第n开始读取到第页') #0,10表示从0 开始读取到第10页 pagelist = user_define.split(',') print int(pagelist[0]),int((pagelist[1] if pagelist[1] else 10)) for i in range(int(pagelist[0]),int((pagelist[1] if pagelist[1] else 10))+1): baike.backPageItems(i)