Python數據分析之糗事百科

最近一直忙著寫材料,沒給大家寫作業(yè)的案例,第二期同學很厲害,都是搶著要作業(yè)做,哈哈,今天我就給大家寫點爬蟲的擴展和數據分析,讓厲害的同學學起來。

代碼

這次除了爬取老師的作業(yè)布置的字段外,還爬取了用戶的一些信息,如圖所示。



之前的作業(yè)亮同學已經詳細講解了,我今天就貼下我的代碼:

import requests
from lxml import etree
import pymongo
import time

client = pymongo.MongoClient('localhost', 27017)
qiushi = client['qiushi']
qiushi_info = qiushi['qiushi_info']
user_info = qiushi['user_info']

header = {
    'User-Agent':'Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36'
}

def get_info(url):
    html = requests.get(url,headers=header)
    selector = etree.HTML(html.text)
    infos = selector.xpath('//div[@class="col1"]/div')
    base_url = 'https://www.qiushibaike.com'
    for info in infos:
        id = info.xpath('div[1]/a[2]/h2/text()')[0] if len(info.xpath('div[1]/a[2]/h2/text()'))==1 else '匿名用戶'
        jug_sex = info.xpath('div[1]/div/@class')
        if len(jug_sex)==0:
            sex = '不詳'
            age = '不詳'
        elif jug_sex[0]=='articleGender manIcon':
            sex = '男'
            age = info.xpath('div[1]/div/text()')[0]
        else:
            sex = '女'
            age = info.xpath('div[1]/div/text()')[0]
        content = info.xpath('a[1]/div/span[1]/text()')[0]
        laugh = info.xpath('div[2]/span[1]/i/text()')[0]
        comment = info.xpath('div[2]/span[2]/a/i/text()')[0] if info.xpath('div[2]/span[2]/a/i/text()') else None
        user_url = base_url + info.xpath('div[1]/a[2]/@href')[0] if info.xpath('div[1]/a[2]/@href') else None
        data ={
            'id':id,
            'sex':sex,
            'age':age,
            'laugh':laugh,
            'comment':comment,
            'user_url':user_url,
            'content':content
        }
        qiushi_info.insert_one(data)
        if user_url == None:
            pass
        else:
            get_user_info(user_url)
    time.sleep(1)

def get_user_info(url):
    html = requests.get(url,headers=header)
    selector = etree.HTML(html.text)
    if selector.xpath('//div[@class="user-block user-setting clearfix"]'):
        pass
    else:
        fans = selector.xpath('//div[2]/div[3]/div[1]/ul/li[1]/text()')[0] if selector.xpath('//div[2]/div[3]/div[1]/ul/li[1]/text()') else None
        topic = selector.xpath('//div[2]/div[3]/div[1]/ul/li[2]/text()')[0] if selector.xpath('//div[2]/div[3]/div[1]/ul/li[2]/text()') else None
        qiushi = selector.xpath('//div[2]/div[3]/div[1]/ul/li[3]/text()')[0] if selector.xpath('//div[2]/div[3]/div[1]/ul/li[3]/text()') else None
        comment_1 = selector.xpath('//div[2]/div[3]/div[1]/ul/li[4]/text()')[0] if selector.xpath('//div[2]/div[3]/div[1]/ul/li[4]/text()') else None
        favour = selector.xpath('//div[2]/div[3]/div[1]/ul/li[5]/text()')[0] if selector.xpath('//div[2]/div[3]/div[1]/ul/li[5]/text()') else None
        handpick = selector.xpath('//div[2]/div[3]/div[1]/ul/li[6]/text()')[0] if selector.xpath('//div[2]/div[3]/div[1]/ul/li[6]/text()') else None
        martial_status = selector.xpath('//div[2]/div[3]/div[2]/ul/li[1]/text()')[0] if selector.xpath('//div[2]/div[3]/div[2]/ul/li[1]/text()') else '不詳'
        constellation = selector.xpath('//div[2]/div[3]/div[2]/ul/li[2]/text()')[0] if selector.xpath('//div[2]/div[3]/div[2]/ul/li[2]/text()') else '不詳'
        profession = selector.xpath('//div[2]/div[3]/div[2]/ul/li[3]/text()')[0] if selector.xpath('//div[2]/div[3]/div[2]/ul/li[3]/text()') else '不詳'
        home = selector.xpath('//div[2]/div[3]/div[2]/ul/li[4]/text()')[0] if selector.xpath('//div[2]/div[3]/div[2]/ul/li[4]/text()') else '不詳'
        qiushi_age = selector.xpath('//div[2]/div[3]/div[2]/ul/li[5]/text()')[0] if selector.xpath('//div[2]/div[3]/div[2]/ul/li[5]/text()') else '不詳'
        # print(fans,topic,qiushi,comment_1,favour,handpick,martial_status,constellation,profession,home,qiushi_age)
        data ={
            'fans':fans,
            'topic':topic,
            'qiushi':qiushi,
            'comment_1':comment_1,
            'favour':favour,
            'handpick':handpick,
            'martial_status':martial_status,
            'constellation':constellation,
            'profession':profession,
            'home':home,
            'qiushi_age':qiushi_age,
            'user_url':url
        }
        user_info.insert_one(data)


if __name__ == '__main__':
    urls = ['https://www.qiushibaike.com/text/page/{}/'.format(str(i)) for i in range(1,36)]
    for url in urls:
        get_info(url)

數據存儲到mongodb數據庫中,如圖:



數據預處理

  • 首先,導入庫和數據:
import pandas as pd
import pymongo
import jieba.analyse
import numpy as np
import matplotlib.pyplot as plt
%matplotlib inline
client = pymongo.MongoClient('localhost',port = 27017)
qiushi = client['qiushi']
qiushi_info = qiushi['qiushi_info']
data = pd.DataFrame(list(qiushi_info.find()))
data
  • 字段類型轉化
    由于有些字段沒有,填充了“不詳”或None,所以age,comment字段都是文本類型的,需轉化為整形,但有None這些東西沒法轉,需要把這些內容替換為“0”才能轉,以下就是轉化代碼。(怎么就管不住我這雙手呢,填空值可以直接轉化,而且填充缺失值也很簡單)
data['age'].replace('不詳','0',inplace=True)
data['comment'].replace([None],'0',inplace=True)
data['age'] = data['age'].astype('int64')
data['comment'] = data['comment'].astype('int64')
data['laugh'] = data['laugh'].astype('int64')
data.dtypes
  • 填補缺失值
    我把一些值都替換成了0,我們通過列的平均值進行填充即可。
data['age'].replace(0,int(data[data['age']!=0]['age'].mean()),inplace=True)
data['comment'].replace(0,int(data[data['comment']!=0]['comment'].mean()),inplace=True)

玩糗事的人年齡

通過describe看下:

data.describe()

可以看出平均年齡為34,話說不是我們才是段子手的主力軍么,我回頭看了下數據,有很多人填寫的年齡為100以上,為虛假信息,由于數據量少,拉高了平均值,段子手是屬于我們的!!!!(我不會告訴你我才17)

誰是段子手

通過排序,找出前十評論和前十好笑的段子的用戶,看看誰才是真正的段子手。

data1 = data.sort_values(['comment'],ascending=False)[0:10]
plt.figure(figsize=(20,10),dpi=80)
lables=list(data1['id'])
plt.bar(range(len(lables)),data1['comment'],tick_label=lables)

data2 = data.sort_values(['laugh'],ascending=False)[0:10]
plt.figure(figsize=(20,10),dpi=80)
lables=list(data1['id'])
plt.bar(range(len(lables)),data1['laugh'],tick_label=lables)

段子手性別比例

看下段子手男女比例:

plt.figure(figsize=(8,6),dpi=80)
labels = list(data3.index)
sizes = list(data3)
colors = ['red','yellowgreen','lightskyblue']

explode = (0.05,0,0)

patches,l_text,p_text = plt.pie(sizes,explode=explode,labels=labels,colors=colors,
                                labeldistance = 1.1,autopct = '%3.1f%%',shadow = False,
                                startangle = 90,pctdistance = 0.6)
plt.axis('equal')
plt.legend()


男生比較多,哈哈,污污的女生最可愛!!!

段子詞云

詞云制作講過很多次了,放上代碼和圖。

duanzi = ''  #初始化字符串
for i in range(360):   #數字為數據的行數
    index = data.ix[i,:]   #取每行
    content = index['content']  #取每行的question
    duanzi = duanzi + content
jieba.analyse.set_stop_words('停用詞表路徑')
tags = jieba.analyse.extract_tags(duanzi, topK=50, withWeight=True)
for item in tags:
    print(item[0]+'\t'+str(int(item[1]*1000)))

段子嘛,無非是男生聊女生,女生聊男生。

總結

放假了,作業(yè)寫完的同學,數據分析來一波,還有用戶的詳細信息沒分析,我們下次分析咯!!端午快樂。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容