从无到有的“糗事百科”分析

2022-04-27 17:38:17 浏览数 (1)

1,麻雀虽小,五脏俱全:

从简单的爬取数据到可视化分析,不仅实践中掌握发现学习Python的乐趣与价值,也在过程中掌握 数据获取,数据清新,数据可视化的整个流程。可谓是“麻雀虽小,五脏俱全“ 。

2,知其然,也知所以然:

从无到有的“糗事百科”分析:利用程序伪造用户浏览器的上下文信息,访问特定的地址,发送请求,接受请求的数据(多为html格式的文本)。

解读文本规则,找到自己想要的数据,利用正则洗出自己想要的数据,存储到文件或数据表中。后续我们可以对存在的数据文件进行一下统计描述,让数据映射为图表。用图说话,胜过万语千言。

环境说明:依赖是Python2

抓取页面:糗事百科 24小时爆笑笑话大全 (页面结构可能变了)

抓取字段:用户昵称,性别,年龄,糗事内容,是否有图,点赞数,喜欢数。

3,我们认识了:糗事百科:

  • 写糗事百科的男性占比高于女性
  • 年龄段集中分布在20到30岁
  • 喜欢写小段子,不喜欢发图片
  • 一入糗百深似海,从此节操为路人

4,分析数据:

数据抓取的代码,放在了文章结尾,供大家学习参考。

对抓取的数据进行多维度的聚合,我们可以得到数据在不同维度上的分布,从简单的多维度数据立方体进行可视化,我们可以从繁多的数据中,发现简单的描述。低成本的认识糗事百科,同样这也是我们简单的认识其它事物的方法之一。

从下图可以看出,用户发布的糗事不添加图片的占比为百分之84。是不是制图发图的时间成本高,希望糗事百科能支持图片在线编辑功能,收藏,转发来刺激用户发图。

从下图可以看到每个年龄到糗事的评论文章长度相当,20到29评论点赞数较高,从上万的点赞数可以看出,糗事百科还是有很多吃瓜群众的

写糗事百科年龄段分布图

写糗事百科男性占比64,是屌丝太多,还是男女比例失衡

欢迎学习,参考:

代码语言:javascript复制
#encoding:utf-8
__author__ = 'herain'
import sys
import urllib
import urllib2
import codecs
import re
import thread
import 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 = '01'
    res = div.join("%s"%str(i).encode('utf-8') for i in datalist)
    res = "%sn"%(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 ,'nn'
      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年龄:%st内容:%st是否有图:%st点赞数:%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)

0 人点赞