一.主題式網絡爬蟲設計方案
1.主題式 網絡爬蟲名稱:爬取百度熱搜排行榜及數據分析與可視化處理
2.主題式網絡爬蟲爬取的內容:爬取百度熱搜排名,標題,熱度值
3.方案設計:訪問分析百度熱搜網頁,得到網頁源代碼,寫出查找所需標簽的代碼,對數據進行相應的分析。提取標簽保存到csv文件中,讀取文件進行數據清洗和數據可視化,繪制圖形進行數據分析。接下來分析排行和熱度的擬合方程並繪制擬合曲線。
技術難點:爬取信息時對標簽的尋找,數據可視化處理時繪制圖形不夠熟練,繪制圖形時運行一直出錯,回歸方程不太理解。
二.頁面結構特征分析
1.找對應的標簽,通過觀察可以發現在tbody中,在tr中找到對應標簽,即排名 在td class=''first'中,標題在第二個td class = 'keyword'中,熱度在最后一個td class = 'last'中。
2.頁面解析
三.1.獲取html網頁
import requests
import re
import pandas as pd
#請求網頁
headers = { 'User-Agent': '5498'}
response = requests.get('https://tophub.today/n/Jb0vmloB1G',headers=headers)
html=response.text
#print(html)
#解析網頁與抓取信息
urls = re.findall('<a href=.*? target="_blank" .*?>(.*?)</a>',html)[3:13]
redu = re.findall('<td>(.*?)</td>',html)[0:10]
a = []#創建空列表
for i in range(10):
a.append([i+1,urls[i],redu[i][:-1]])
#完成創建
#使用pandans保存數據
from pandas.core.frame import DataFrame
dict = pd.DataFrame(a,columns = ['排名','標題','熱度(單位:萬)'])
data = pd.DataFrame(dict)
print(data)
#生成CSV文件
filename="百度熱搜榜.csv"
data.to_csv(filename,index=False)
2.數據清洗
#讀取csv文件
df=pd.DataFrame(pd.read_csv('redian.csv'))
print(df)
#刪除無效列與行
#df.drop('標題', axis=1, inplace = True)
#df.head()
#重復值處理
print(df.duplicated())
#檢查是否有空值
print(df['熱度'].isnull().value_counts())
#異常值處理
print(df.describe())
# 將數據統計信息打印出來
print(df.describe())
3.數據分析與可視化
(1) from sklearn.linear_model import LinearRegression
X = df.drop("標題",axis=1)
predict_model = LinearRegression()
predict_model.fit(X,df['熱度'])
print("回歸系數為:",predict_model.coef_)
#繪制排名與熱度的回歸圖
import seaborn as sns
sns.regplot(df.排名,df.熱度)
(2)#繪制圖形
#繪制條形圖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['Arial Unicode Ms']#用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus']=False#用來正確顯示負號
data=np.array([532.1,386.6,378.7,333.5,330.4,297.2,285.4,239.8,159.1,135.3])
index=['1','2','3','4','5','6','7','8','9','10']
s = pd.Series(data,index)
s.name='百度熱搜條形圖'
s.plot(kind='bar',title='百度熱搜條形圖')
plt.show()
#繪制散點圖
def scatter():
plt.scatter(df.排名, df.熱度, color='green', s=10, marker="o")
plt.xlabel("排名")
plt.ylabel("熱度")
plt.title("排名與熱度散點圖")
plt.show()
scatter()
#繪制盒圖
def box_diagram():
plt.title('繪制排名與熱度-箱體圖')
sns.boxplot(x='排名',y='熱度', data=df)
box_diagram()
#繪制折線圖
def line_diagram():
x = df['排名']
y = df['熱度']
plt.xlabel('排名')
plt.ylabel('熱度')
plt.plot(x,y)
plt.scatter(x,y)
plt.title("排名與熱度折線圖")
plt.show()
line_diagram()
(3)#繪制分布圖
sns.jointplot(x="排名",y='熱度',data = df)
sns.jointplot(x="排名",y='熱度',data = df, kind='reg')
sns.jointplot(x="排名",y='熱度',data = df, kind='hex')
sns.jointplot(x="排名",y='熱度',data = df, kind='kde', color='r')
sns.kdeplot(df['排名'], df['熱度'])
(4)#選擇排名和熱度兩個特征變量,繪制分布圖,用最小二乘法分析兩個變量間的二次擬合方程和擬合曲線
colnames=[" ","排名","標題","熱度"]
df = pd.read_csv('百度熱搜榜.csv',skiprows=1,names=colnames)
X = df.排名
Y = df.熱度
Z = df.標題
def A():
plt.scatter(X,Y,color="red",linewidth=2)
plt.title("RM scatter",color="red")
plt.grid()
plt.show()
def B():
plt.scatter(X,Y,color="green",linewidth=2)
plt.title("redu",color="red")
plt.grid()
plt.show()
def func(p,x):
a,b,c=p
return a*x*x+b*x+c
def error(p,x,y):
return func(p,x)-y
def main():
plt.figure(figsize=(10,6))
p0=[0,0,0]
Para = leastsq(error,p0,args=(X,Y))
a,b,c=Para[0]
print("a=",a,"b=",b,"c=",c)
plt.scatter(X,Y,color="red",linewidth=2)
x=np.linspace(0,10,10)
y=a*x*x+b*x+c
plt.plot(x,y,color="red",linewidth=2,)
plt.title("熱度值分布")
plt.grid()
plt.show()
print(A())
print(B())
print(main())
四.完整代碼
import requests import re import pandas as pd #請求網頁 headers = { 'User-Agent': '5498'} response = requests.get('https://tophub.today/n/Jb0vmloB1G',headers=headers) html=response.text #print(html) #解析網頁與抓取信息 urls = re.findall('<a href=.*? target="_blank" .*?>(.*?)</a>',html)[3:13] redu = re.findall('<td>(.*?)</td>',html)[0:10] a = []#創建空列表 for i in range(10): a.append([i+1,urls[i],redu[i][:-1]]) #完成創建 #使用pandans保存數據 from pandas.core.frame import DataFrame dict = pd.DataFrame(a,columns = ['排名','標題','熱度(單位:萬)']) data = pd.DataFrame(dict) print(data) #生成CSV文件 filename="百度熱搜榜.csv" data.to_csv(filename,index=False)
#刪除無效列與行
#df.drop('標題', axis=1, inplace = True)
#df.head()
#重復值處理
print(df.duplicated())
#檢查是否有空值
print(df['熱度'].isnull().value_counts())
#異常值處理
print(df.describe())
# 將數據統計信息打印出來
print(df.describe())
(1) from sklearn.linear_model import LinearRegression
X = df.drop("標題",axis=1)
predict_model = LinearRegression()
predict_model.fit(X,df['熱度'])
print("回歸系數為:",predict_model.coef_)
#繪制排名與熱度的回歸圖
import seaborn as sns
sns.regplot(df.排名,df.熱度)
(2)#繪制圖形
#繪制條形圖
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
plt.rcParams['font.sans-serif']=['Arial Unicode Ms']#用來正常顯示中文標簽
plt.rcParams['axes.unicode_minus']=False#用來正確顯示負號
data=np.array([532.1,386.6,378.7,333.5,330.4,297.2,285.4,239.8,159.1,135.3])
index=['1','2','3','4','5','6','7','8','9','10']
s = pd.Series(data,index)
s.name='百度熱搜條形圖'
s.plot(kind='bar',title='百度熱搜條形圖')
plt.show()
#繪制散點圖
def scatter():
plt.scatter(df.排名, df.熱度, color='green', s=10, marker="o")
plt.xlabel("排名")
plt.ylabel("熱度")
plt.title("排名與熱度散點圖")
plt.show()
scatter()
#繪制盒圖
def box_diagram():
plt.title('繪制排名與熱度-箱體圖')
sns.boxplot(x='排名',y='熱度', data=df)
box_diagram()
#繪制折線圖
def line_diagram():
x = df['排名']
y = df['熱度']
plt.xlabel('排名')
plt.ylabel('熱度')
plt.plot(x,y)
plt.scatter(x,y)
plt.title("排名與熱度折線圖")
plt.show()
line_diagram()
#繪制分布圖
sns.jointplot(x="排名",y='熱度',data = df)
sns.jointplot(x="排名",y='熱度',data = df, kind='reg')
sns.jointplot(x="排名",y='熱度',data = df, kind='hex')
sns.jointplot(x="排名",y='熱度',data = df, kind='kde', color='r')
sns.kdeplot(df['排名'], df['熱度'])
#選擇排名和熱度兩個特征變量,繪制分布圖,用最小二乘法分析兩個變量間的二次擬合方程和擬合曲線
colnames=[" ","排名","標題","熱度"]
df = pd.read_excel('rank.xlsx',skiprows=1,names=colnames)
X = df.排名
Y = df.熱度
Z = df.標題
def A():
plt.scatter(X,Y,color="blue",linewidth=2)
plt.title("RM scatter",color="blue")
plt.grid()
plt.show()
def B():
plt.scatter(X,Y,color="green",linewidth=2)
plt.title("redu",color="blue")
plt.grid()
plt.show()
def func(p,x):
a,b,c=p
return a*x*x+b*x+c
def error(p,x,y):
return func(p,x)-y
def main():
plt.figure(figsize=(10,6))
p0=[0,0,0]
Para = leastsq(error,p0,args=(X,Y))
a,b,c=Para[0]
print("a=",a,"b=",b,"c=",c)
plt.scatter(X,Y,color="blue",linewidth=2)
x=np.linspace(0,10,10)
y=a*x*x+b*x+c
plt.plot(x,y,color="blue",linewidth=2,)
plt.title("熱度值分布")
plt.grid()
plt.show()
print(A())
print(B())
print(main())
五.總結
1.經過數據的分析和可視化的回歸曲線可以看出熱度和排名呈正相關,熱度會隨排名的降低呈現下降,圖表可以更為直觀的表現出排名與熱度的關系以及它們的變化范圍與程度。
2.小結:在這次的程序設計中我遇到了許多困難,首先在爬取信息時對標簽的尋找,無法從標簽中找到有效信息,在對數據進行清理時不能熟練的掌握各個信息庫,很多方法不會使用,經常借助百度等工具,不會的問題也有求助同學。對代碼的表達上不夠流暢,速度慢,准確度低,也認識到了自身的不足,也能夠加深對Python這門課程的理解。也因為經常性的代碼出錯,導致我以后能更加認真的檢查,也加深了對語法函數的理解,對以后的學習提高更好的能力,掌握更深的知識。