一.主題式網絡主題式網絡爬蟲設計方案
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庫的掌握對我今后的爬蟲設計上也是非常有用的。這次設計也讓我意識到了自己的不足,例如 獲取數據時如果能掌握正則表達式 就會更加簡潔迅速 我也還需要進行進步學習。