爬取微博熱搜榜並進行數據分析


一.主題式網絡主題式網絡爬蟲設計方案

1.爬蟲名稱:爬取微博熱搜榜

2.爬蟲爬取的內容:爬取微博熱搜榜數據。 

3.網絡爬蟲設計方案概述:用requests庫訪問頁面用get方法獲取頁面資源,登錄頁面對頁面HTML進行分析,用beautifulsoup庫獲取並提取自己所需要的信息。再講數據保存到CSV文件中,進行數據清洗,數據可視化分析,繪制數據圖表,並用最小二乘法進行擬合分析。

二、主題頁面的結構特征分析

1.主題頁面的結構與特征分析:通過觀察頁面HTML源代碼,可以發現每個熱搜名稱的標題都位於"td",class_='td-02'標簽的子標簽中,熱度和排名則分布在"td",class_='td-03'和"td",class_='td-01'標簽中,他們的關系是 class>a>span。按照標簽的從屬關系 可從標簽中遍歷出我們所需要的內容。

2.Htmls頁面解析

通過頁面定位分析發現這是標題所在標簽位置,td",class_='td-02“的子標簽a 中,我們可以通過find all 函數來提取我們所需要的標題信息

 

繼續審查頁面元素 發現熱度和排名所在的標簽位置,查到所需要的內容的標簽位置后,就可以開始編寫我的爬蟲程序了

三、網絡爬蟲程序設計

1.數據爬取與采集 

import requests
from bs4 import BeautifulSoup
import bs4
#定義函數第一步從網絡上獲取熱搜排名網頁內容
url = "https://s.weibo.com/top/summary?Refer=top_hot&topnav=1&wvr=6"
def getHTMLText(url):
    try:
        #設置表頭信息
        kv={"User-Agent":"Mozilla/5.0"} 
        r = requests.get(url, headers=kv, timeout=30)  #請求時間30s
        # 解決亂碼問題
        r.raise_for_status() 
        r.encoding=r.apparent_encoding  #修改編碼方式
        return r.text
    except:
        return ""  #若出現異常則會返回空字符串
#使用BeautifulSoup工具解析頁面
html = getHTMLText(url)
soup=BeautifulSoup(html,'html.parser')
# 爬取熱搜名字
sou = soup.find_all("td",class_='td-02')
#創立空列表 把熱搜名字數據填入
name = []
for x in sou:
    name.append(x.a.string)
# 獲取熱度排名 
# 同理創立空列表
paiming = []
top = soup.find_all('span')
for y in top:
    paiming.append(y.string)
#用字符串格式化輸出數據
print('{:^40}'.format('微博熱搜'))
print('{:^15}\t{:^25}\t{:^40}'.format('排名', '熱搜內容', '熱度'))
list = []
#輸出數據的前20條
for i in range(21):
    print('{:^15}\t{:^25}\t{:^40}'.format(i+1, name[i], paiming[i]))
    list.append([i+1,name[i],paiming[i]])
#用pandas對數據進行儲存,並生成文件
df= pd.DataFrame(list,columns = ['排名','熱搜內容','熱度'])
df.to_csv('resou.csv')

 

 

 生成文件

 

 

 

 

 

 

 2.對數據進行清洗和處理

#讀取文件
df = pd.DataFrame(pd.read_csv('resou.csv'))
#輸出信息
print(df)

#開始進行數據清洗
#刪除無效列與行
df.drop('熱搜內容', axis=1, inplace = True)
df.head() #輸出數據前五行

#檢查是否有重復值
df.duplicated()  

#檢查是否有空值
print(df['熱度'].isnull().value_counts())
#若有則刪除缺失值
df[df.isnull().values==True]
df.corr()

# 將數據統計信息打印出來
df.describe()

 

 3.數據分析與可視化

#繼續數據分析與可視化
# 構建線性回歸預測模型
from sklearn.linear_model import LinearRegression
X = df.drop("熱度", axis = 1)
predict_model = LinearRegression()
predict_model.fit(X, df['排名'])    #訓練模型
print("回歸系數為:", predict_model.coef_)   # 判斷相關性

 

 

 

#繪制散點圖
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
import numpy as np
%matplotlib inline  
排名 = (df["排名"])
熱度 = (df["熱度"])
plt.rcParams['font.sans-serif']=['SimHei'] #用於正常顯示中文標簽
plt.figure(figsize=(8,5))
plt.scatter(排名,熱度,color=[0,0,1,0.4],label=u"樣本數據",linewidth=2)  #顏色用RGB值
plt.title("排名 scatter",color="blue")
plt.xlabel("排名")
plt.ylabel("熱度")
plt.legend()
plt.grid()
plt.show()

#回歸散點圖
import seaborn as sns
sns.regplot(df.排名,df.熱度)
plt.title('排名熱度回歸散點圖')

#繪制柱狀圖
plt.figure()
x=np.arange(0,20)
y=df.loc['1':'20','熱度']  #選取畫圖數據范圍
plt.bar(x, y,color='c',alpha=0.5) #增加透明度 使圖更加美觀
plt.xlabel('排名')
plt.ylabel('熱度')
plt.title("熱搜數據")
plt.show()

 

 

# 繪制折線圖
plt.figure()
plt.rcParams['font.sans-serif']=['SimHei'] #用來正常顯示中文標簽
x=np.arange(0,20)
y=df.loc['1':'20','熱度']  #選取畫圖數據范圍
plt.plot(x, y,'r-o',color='blue')
plt.xlabel('排名')
plt.ylabel('熱度')
plt.title("熱搜數據")
plt.show()

 

 

#繪制盒圖
def box():
    plt.title('熱度與排名盒圖')
    sns.boxplot(x='排名',y='熱度', data=df)
box()

 

 

#用Seaborn繪制各種分布圖
import seaborn as sns
sns.jointplot(x="排名",y='熱度',data = df, kind='kde', color='r')
sns.jointplot(x="排名",y='熱度',data = df, kind='hex')
sns.distplot(df['熱度'])

 

 

# 繪制單核密度圖
sns.kdeplot(df['熱度'])

 

 

#繪制排名與熱度的回歸圖
sns.regplot(df.排名,df.熱度)

 

 4..根據排名與熱度數據之間的關系,分析兩個變量擬合一元二次曲線,建立變量之間的回歸方程

# 用最小二乘法得出一元二次擬合方程
import numpy as np
from numpy import genfromtxt
import scipy as sp
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
plt.figure(figsize=(13,6))
plt.scatter(排名,熱度,color=[0,0,0.8,0.4],label=u"樣本數據",linewidth=2)
plt.xlabel("排名")
plt.ylabel("熱度")
plt.legend()
def func(p,x):
    a,b,c=p
    return a*(x**2)+(b*x)+c
def er_func(p,x,y):
    return func(p,x)-y
p0=[2,3,4]
P=leastsq(er_func,p0,args=(排名,熱度))
a,b,c=P[0]
x=np.linspace(0,55,100)
y=a*(x**2)+(b*x)+c
plt.plot(x,y,color=[0,0,0.8,0.4],label=u"擬合直線",linewidth=2)
plt.scatter(x,y,color="c",label=u"樣本數據",linewidth=2)
plt.legend()
plt.title('排名熱度回歸曲線')
plt.grid()
plt.show()

 

 5.將以上各部分的代碼匯總,附上完整程序代碼

 

import requests
from bs4 import BeautifulSoup
import bs4
import pandas as pd   #引入pandas用於數據可視化
from pandas import DataFrame
import seaborn as sns
import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import leastsq
from sklearn.linear_model import LinearRegression
#定義函數第一步從網絡上獲取熱搜排名網頁內容
url = "https://s.weibo.com/top/summary?Refer=top_hot&topnav=1&wvr=6"
def getHTMLText(url):
    try:
        #設置表頭信息
        kv={"User-Agent":"Mozilla/5.0"} 
        r = requests.get(url, headers=kv, timeout=30)  #請求時間30s
        # 解決亂碼問題
        r.raise_for_status() 
        r.encoding=r.apparent_encoding  #修改編碼方式
        return r.text
    except:
        return ""  #若出現異常則會返回空字符串

#使用BeautifulSoup工具解析頁面 html = getHTMLText(url) soup=BeautifulSoup(html,'html.parser')

# 爬取熱搜名字 sou = soup.find_all("td",class_='td-02')

#創立空列表 把熱搜名字數據填入 name = [] for x in sou: name.append(x.a.string)

# 獲取熱度排名 # 同理創立空列表 paiming = [] top = soup.find_all('span') for y in top: paiming.append(y.string)

#用字符串格式化輸出數據 print('{:^40}'.format('微博熱搜')) print('{:^15}\t{:^25}\t{:^40}'.format('排名', '熱搜內容', '熱度')) list = []

#輸出數據的前20條 for i in range(21): print('{:^15}\t{:^25}\t{:^40}'.format(i+1, name[i], paiming[i])) list.append([i+1,name[i],paiming[i]])

#用pandas對數據進行儲存,並生成文件 df= pd.DataFrame(list,columns = ['排名','熱搜內容','熱度']) df.to_csv('resou.csv')

#讀取文件 df = pd.DataFrame(pd.read_csv('resou.csv')) #輸出信息 print(df)

#開始進行數據清洗 #刪除無效列與行 df.drop('熱搜內容', axis=1, inplace = True) df.head() #輸出數據前五行


#檢查是否有重復值 df.duplicated()

#檢查是否有空值 print(df['熱度'].isnull().value_counts()) #若有則刪除缺失值 df[df.isnull().values==True] df.corr()

# 將數據統計信息打印出來 df.describe()

#進行數據分析與可視化 X = df.drop("熱度", axis = 1) predict_model = LinearRegression() predict_model.fit(X, df['排名']) #訓練模型 print("回歸系數為:", predict_model.coef_) # 判斷相關性


#繪制散點圖 import matplotlib.pyplot as plt from scipy.optimize import leastsq import numpy as np %matplotlib inline 排名 = (df["排名"]) 熱度 = (df["熱度"]) plt.rcParams['font.sans-serif']=['SimHei'] #用於正常顯示中文標簽 plt.figure(figsize=(8,5)) plt.scatter(排名,熱度,color=[0,0,1,0.4],label=u"樣本數據",linewidth=2) #顏色用RGB值 plt.title("排名 scatter",color="blue") plt.xlabel("排名") plt.ylabel("熱度") plt.legend() plt.grid() plt.show()

#回歸散點圖 import seaborn as sns sns.regplot(df.排名,df.熱度) plt.title('排名熱度回歸散點圖')

#繪制柱狀圖 plt.figure() x=np.arange(0,20) y=df.loc['1':'20','熱度'] #選取畫圖數據范圍 plt.bar(x, y,color='c',alpha=0.5) #增加透明度 使圖更加美觀 plt.xlabel('排名') plt.ylabel('熱度') plt.title("熱搜數據") plt.show()

# 繪制折線圖 plt.figure() plt.rcParams['font.sans-serif']=['SimHei'] #用來正常顯示中文標簽 x=np.arange(0,20) y=df.loc['1':'20','熱度'] #選取畫圖數據范圍 plt.plot(x, y,'r-o',color='blue') plt.xlabel('排名') plt.ylabel('熱度') plt.title("熱搜數據") plt.show()

#繪制盒圖 def box(): plt.title('熱度與排名盒圖') sns.boxplot(x='排名',y='熱度', data=df) box()

#用Seaborn繪制各種分布圖 sns.jointplot(x="排名",y='熱度',data = df, kind='kde', color='r') sns.jointplot(x="排名",y='熱度',data = df, kind='hex') sns.distplot(df['熱度'])

# 繪制單核密度圖 sns.kdeplot(df['熱度'])

#繪制排名與熱度的回歸圖 sns.regplot(df.排名,df.熱度)

# 用最小二乘法得出一元二次擬合方程 plt.figure(figsize=(13,6)) plt.scatter(排名,熱度,color=[0,0,0.8,0.4],label=u"樣本數據",linewidth=2) plt.xlabel("排名") plt.ylabel("熱度") plt.legend() def func(p,x): a,b,c=p return a*(x**2)+(b*x)+c def er_func(p,x,y): return func(p,x)-y p0=[2,3,4] P=leastsq(er_func,p0,args=(排名,熱度)) a,b,c=P[0] x=np.linspace(0,55,100) y=a*(x**2)+(b*x)+c plt.plot(x,y,color=[0,0,0.8,0.4],label=u"擬合直線",linewidth=2) plt.scatter(x,y,color="c",label=u"樣本數據",linewidth=2) plt.legend() plt.title('排名熱度回歸曲線') plt.grid() plt.show()

 

四、結論

1:通過對熱搜主題的數據分析與可視化的回歸曲線可以看出 熱度和排名是成正相關的,數據的可視化與圖表可以清晰明了的將數據的關系體現出來,讓我們直觀的了解熱度和排名的變化。

2.對本次程序設計任務完成的情況做一個簡單的小結。

此次程序設計我遇到了許多困難,初期對HTML頁面的不熟悉,無法從眾多標簽中提取到自己的有用信息。一次次程序的出錯,讓我不斷的去百度查閱資料和視頻一次次的去解決,很好的鍛煉了我的耐心,和代碼的准確表達能力。也是通過這次設計我很好的學習了BeautifulSoup庫的使用,並將它初步熟練掌握。BeautifulSoup庫在用於HTML解析和提取相關信息方面是非常優秀的,BeautifulSoup庫的掌握對我今后的爬蟲設計上也是非常有用的。這次設計也讓我意識到了自己的不足,例如 獲取數據時如果能掌握正則表達式 就會更加簡潔迅速 我也還需要進行進步學習。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM