------主題式網絡主題式網絡爬蟲設計方案------
1.爬蟲名稱:爬取微博熱搜
2.爬蟲爬取的內容:爬取微博熱搜數據。 數據特征分析:各數據分布緊密聯系。
3.網絡爬蟲設計方案概述:
實現思路:通過訪問網頁源代碼使用xpath正則表達爬取數據,對數據進行保存數據,再對數據進行清洗和處理,數據分析與可視化處理。
技術難點:在編程的過程中,若中間部分出現錯誤,可能導致整個代碼需要重新修改。數據實時更新,會導致部分上傳的圖形不一致。
------主題頁面的結構特征分析------
1.主題頁面的結構和特征分析:爬取數據都分布在標簽'div.cc-cd-cb nano has-scrollbar'里面,標題標簽為'span.t',熱度標簽為'span.e'。
2.Htmls頁面解析:
3.節點(標簽)查找方法與遍歷方法:通過xpath遍歷標簽。利用xpath正則表達查找。
------網絡爬蟲程序設計------
import requests from lxml import etree import pandas as pd import numpy as np import matplotlib.pyplot as plt import matplotlib from scipy.optimize import leastsq import scipy.stats as sts import seaborn as sns url = "https://tophub.today/" headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'} html = requests.get(url,headers = headers) html = html.content.decode('utf-8') html = etree.HTML(html) div = html.xpath("//div[@id='node-1']/div") for a in div: titles = a.xpath(".//span[@class='t']/text()") numbers = a.xpath(".//span[@class='e']/text()") b = [] for i in range(25): b.append([i+1,titles[i],numbers[i][:-1]]) file = pd.DataFrame(b,columns = ['排名','今日熱搜','熱度(單位為萬)']) print(file) file.to_csv('微博熱搜榜熱度數據.csv')
2.對數據進行清洗和處理:
df = pd.DataFrame(pd.read_csv('微博熱搜榜熱度數據.csv')) df.head()
df.drop('今日熱搜', axis=1, inplace=True) df.head()
df.isnull().sum()
df[df.isnull().values==True]
df.describe()
3.數據分析與可視化:
df.corr()
sns.lmplot(x='排名',y='熱度(單位為萬)',data=df)
def one(): file_path = "'微博熱搜榜熱度數據.csv'" x = df['排名'] y = df['熱度(單位為萬)'] plt.xlabel('排名') plt.ylabel('熱度(單位為萬)') plt.bar(x,y) plt.title("繪制排名與熱度條形圖") plt.show() one()
def two(): x = df['排名'] y = df['熱度(單位為萬)'] plt.xlabel('排名') plt.ylabel('熱度(單位為萬)') plt.plot(x,y) plt.scatter(x,y) plt.title("繪制排名與熱度折線圖") plt.show() two()
def three(): x = df['排名'] y = df['熱度(單位為萬)'] plt.xlabel('排名') plt.ylabel('熱度(單位為萬)') plt.scatter(x,y,color="red",label=u"熱度分布數據",linewidth=2) plt.title("繪制排名與熱度散點圖") plt.legend() plt.show() three()
4.根據數據之間的關系,分析兩個變量之間的相關系數,畫出散點圖,並建立變量之間的回歸方程:
一元一次回歸方程:
def main(): colnames = ["排名","今日熱搜","number"] #由於運行存在問題,用number表示'熱度(單位為萬)' f = pd.read_csv('微博熱搜榜熱度數據.csv',skiprows=1,names=colnames) X = f.排名 Y = f.number def func(p,x): k,b = p return k*x+b def error_func(p,x,y): return func(p,x)-y p0 = [1,20] Para = leastsq(error_func,p0,args = (X,Y)) k,b = Para[0] print("k=",k,"b=",b) plt.figure(figsize=(8,6)) plt.scatter(X,Y,color="green",label=u"熱度分布",linewidth=2) x=np.linspace(0,30,25) y=k*x+b plt.plot(x,y,color="red",label=u"回歸方程直線",linewidth=2) plt.title("微博今日熱搜排名和熱度關系圖") plt.xlabel('排名') plt.ylabel('熱度(單位為萬)') plt.legend() plt.show() main()
一元二次回歸方程:
def four(): colnames = ["排名","今日熱搜","number"] #由於運行存在問題,用number表示'熱度(單位為萬)' f = pd.read_csv('微博熱搜榜熱度數據.csv',engine='python',skiprows=1,names=colnames) X = f.排名 Y = f.number def func(p,x): a,b,c=p return a*x*x+b*x+c def error_func(p,x,y): return func(p,x)-y p0=[0,0,0] Para=leastsq(error_func,p0,args=(X,Y)) a,b,c=Para[0] plt.figure(figsize=(10,6)) plt.scatter(X,Y,color="green",label=u"熱度分布",linewidth=2) x=np.linspace(0,30,25) y=a*x*x+b*x+c plt.plot(x,y,color="red",label=u"回歸方程直線",linewidth=2) plt.title("微博今日熱搜排名和熱度關系圖") plt.xlabel('排名') plt.ylabel('熱度(單位為萬)') plt.legend() plt.show() four()
5.完整代碼:
1 import requests 2 from lxml import etree 3 import pandas as pd 4 import numpy as np 5 import matplotlib.pyplot as plt 6 import matplotlib 7 from scipy.optimize import leastsq 8 import scipy.stats as sts 9 import seaborn as sns 10 11 12 url = "https://tophub.today/" 13 headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.102 Safari/537.36 Edge/18.18362'} 14 html = requests.get(url,headers = headers)#發送get請求 15 #print(html.text)#獲取源代碼 16 17 18 19 html = html.content.decode('utf-8')#配置編碼 20 html = etree.HTML(html)#構建一個xpath解析對象 21 22 div = html.xpath("//div[@id='node-1']/div") 23 for a in div:#遍歷標簽 24 titles = a.xpath(".//span[@class='t']/text()")#xpath正則表達 25 numbers = a.xpath(".//span[@class='e']/text()")#xpath正則表達 26 27 28 29 b = []#創建一個空列表 30 for i in range(25): 31 b.append([i+1,titles[i],numbers[i][:-1]])#拷貝前25組數據 32 file = pd.DataFrame(b,columns = ['排名','今日熱搜','熱度(單位為萬)']) 33 #print(file) 34 35 file.to_csv('微博熱搜榜熱度數據.csv',encoding = 'gbk')#保存文件,數據持久化 36 37 38 #讀取csv文件 39 df = pd.DataFrame(pd.read_csv("微博熱搜榜熱度數據.csv",engine='python')) 40 df.head() 41 42 43 #刪除無效列與行 44 df.drop('今日熱搜', axis=1, inplace=True) 45 df.head() 46 47 48 #空值處理 49 df.isnull().sum()#返回0,表示沒有空值 50 51 52 #缺失值處理 53 df[df.isnull().values==True]#返回無缺失值 54 55 56 57 #用describe()命令顯示描述性統計指標 58 df.describe() 59 60 #用corr()顯示各數據間的相關系數 61 df.corr() 62 63 64 plt.rcParams['font.sans-serif'] = ['SimHei'] 65 66 plt.rcParams['axes.unicode_minus'] = False 67 68 69 #用seabron.lmplot()方法,建立排名和熱度(單位為萬)之間的線性關系 70 sns.lmplot(x='排名',y='熱度(單位為萬)',data=df) 71 72 73 74 #繪制排名與熱度條形圖 75 def one(): 76 file_path = "'微博熱搜榜熱度數據.csv'" 77 x = df['排名'] 78 y = df['熱度(單位為萬)'] 79 plt.xlabel('排名') 80 plt.ylabel('熱度(單位為萬)') 81 plt.bar(x,y) 82 plt.title("繪制排名與熱度條形圖") 83 plt.show() 84 one() 85 86 87 88 #繪制排名與熱度折線圖 89 def two(): 90 x = df['排名'] 91 y = df['熱度(單位為萬)'] 92 plt.xlabel('排名') 93 plt.ylabel('熱度(單位為萬)') 94 plt.plot(x,y) 95 plt.scatter(x,y) 96 plt.title("繪制排名與熱度折線圖") 97 plt.show() 98 two() 99 100 101 #繪制排名與熱度散點圖 102 def three(): 103 x = df['排名'] 104 y = df['熱度(單位為萬)'] 105 plt.xlabel('排名') 106 plt.ylabel('熱度(單位為萬)') 107 plt.scatter(x,y,color="red",label=u"熱度分布數據",linewidth=2) 108 plt.title("繪制排名與熱度散點圖") 109 plt.legend() 110 plt.show() 111 three() 112 113 114 #繪制一元一次方程 115 def main(): 116 colnames = ["排名","今日熱搜","number"] #由於運行存在問題,用number表示'熱度(單位為萬)' 117 f = pd.read_csv('微博熱搜榜熱度數據.csv',engine='python',skiprows=1,names=colnames) 118 X = f.排名 119 Y = f.number 120 121 122 def func(p,x): 123 k,b = p 124 return k*x+b 125 126 127 def error_func(p,x,y): 128 return func(p,x)-y 129 p0 = [1,20] 130 Para = leastsq(error_func,p0,args = (X,Y)) 131 k,b = Para[0] 132 133 print("k=",k,"b=",b) 134 135 plt.figure(figsize=(8,6)) 136 plt.scatter(X,Y,color="green",label=u"熱度分布",linewidth=2) 137 x=np.linspace(0,30,25) 138 y=k*x+b 139 140 plt.plot(x,y,color="red",label=u"回歸方程直線",linewidth=2) 141 plt.title("微博今日熱搜排名和熱度關系圖") 142 plt.xlabel('排名') 143 plt.ylabel('熱度(單位為萬)') 144 plt.legend() 145 plt.show() 146 main() 147 148 149 #繪制一元二次方程 150 def four(): 151 152 colnames = ["排名","今日熱搜","number"] #由於運行存在問題,用number表示'熱度(單位為萬)' 153 f = pd.read_csv('微博熱搜榜熱度數據.csv',engine='python',skiprows=1,names=colnames) 154 X = f.排名 155 Y = f.number 156 157 def func(p,x): 158 a,b,c=p 159 return a*x*x+b*x+c 160 161 def error_func(p,x,y): 162 return func(p,x)-y 163 164 p0=[0,0,0] 165 Para=leastsq(error_func,p0,args=(X,Y)) 166 a,b,c=Para[0] 167 plt.figure(figsize=(10,6)) 168 plt.scatter(X,Y,color="green",label=u"熱度分布",linewidth=2) 169 170 x=np.linspace(0,30,25) 171 y=a*x*x+b*x+c 172 173 plt.plot(x,y,color="red",label=u"回歸方程直線",linewidth=2) 174 plt.title("微博今日熱搜排名和熱度關系圖") 175 plt.xlabel('排名') 176 plt.ylabel('熱度(單位為萬)') 177 plt.legend() 178 plt.show() 179 180 four()
總結:通過方程圖可以更直觀的看出熱搜與熱度之間的關系