Python網路爬蟲-網易新聞資料分析
一、選題的背景
為什麼要選擇此選題?要達到的資料分析的預期目標是什麼?
隨著社會日新月異和網際網路進入大資料時代,自媒體得到了迅猛的發展,人們獲取新聞資訊的方式越來越多,接觸和使用新聞資訊的方式正在逐漸改變,受眾從被動接受資訊到按需主動搜尋資訊,而新聞的種類繁多雜亂,各類人需要的新聞也不盡相同,為此當前以今日頭條為代表的各大媒體通過資料分析,資料探勘等方式,在內容生產上做到精確定位使用者需求,著力打造消費痛點等特點。因此,開發一款新聞定製推送系統有助於為人們提供更為優質的新聞資訊推送服務,人們完全可以根據自己的喜好定製報紙和雜誌,隨著人們使用時間的增長,可以做到“機器越來越懂你”。
本次實驗目的是爬蟲網易新聞,首先利用爬蟲工具將獲取新聞資料,然後進行分析的結果視覺化輸出。
二、主題式網路爬蟲設計方案
1.主題式網路爬蟲名稱
網易新聞資料分析
2.主題式網路爬蟲爬取的內容與資料特徵分析
爬取網易新聞介面資訊,選取了國內、國際、軍事、航空、科技這五個分類進行資料分析
3.主題式網路爬蟲設計方案概述(包括實現思路與技術難點)
本爬蟲主要從一下幾個方面進行設計:匯入需要用到的庫,獲取介面,資料分析,將資料儲存至新聞資料集.csv檔案裡,然後根據爬取到的資料做視覺化分析.
三、主題頁面的結構特徵分析
1.主題頁面的結構與特徵分析
資料來源:https://news.163.com/
2.Htmls 頁面解析
四、網路爬蟲程式設計
爬蟲程式主體要包括以下各部分,要附原始碼及較詳細註釋,並在每部分程式後
面提供輸出結果的截圖。
1.資料爬取與採集
匯入相關庫
1 import requests 2 import json 3 import re 4 5 import pandas as pd 6 import numpy as np 7 8 from sklearn.naive_bayes import MultinomialNB 9 from sklearn.model_selection import train_test_split 10 from sklearn.metrics import accuracy_score, confusion_matrix,f1_score,classification_report11 from sklearn.feature_extraction.text import TfidfTransformer 12 from sklearn.feature_extraction.text import TfidfVectorizer 13 14 import jieba as jb 15 import matplotlib.pyplot as plt 16 import itertools 17 plt.rcParams['font.sans-serif']="SimHei" 18 plt.rcParams['axes.unicode_minus']=False 19 import warnings 20 warnings.filterwarnings('ignore') 21 #要爬取的新聞分類地址國內、國際、軍事、航空、科技 22 url_list={'國內':[ 'https://temp.163.com/special/00804KVA/cm_guonei.js?callback=data_callback', 23 'https://temp.163.com/special/00804KVA/cm_guonei_0{}.js?callback=data_callback'], 24 '國際':['https://temp.163.com/special/00804KVA/cm_guoji.js?callback=data_callback', 25 'https://temp.163.com/special/00804KVA/cm_guoji_0{}.js?callback=data_callback'], 26 '軍事':['https://temp.163.com/special/00804KVA/cm_war.js?callback=data_callback', 27 'https://temp.163.com/special/00804KVA/cm_war_0{}.js?callback=data_callback'], 28 '航空':['https://temp.163.com/special/00804KVA/cm_hangkong.js?callback=data_callback&a=2', 29 'https://temp.163.com/special/00804KVA/cm_hangkong_0{}.js?callback=data_callback&a=2'], 30 '科技':['https://tech.163.com/special/00097UHL/tech_datalist.js?callback=data_callback', 31 'https://tech.163.com/special/00097UHL/tech_datalist_0{}.js?callback=data_callback']}
爬取資料
1 def parse_class(url): 2 '''獲取分類下的新聞''' 3 req=requests.get(url) 4 text=req.text 5 res=re.findall("title(.*?)\\n",text) 6 #去除不規範的符號 7 for i in range(len(res)): 8 res[i]=re.sub("\'|\"|\:|'|,|","",res[i]) 9 return res 10 titles=[] 11 categories=[] 12 def get_result(url): 13 global titles,categories 14 temp=parse_class(url) 15 if temp[0]=='>網易-404</title>': 16 return False 17 print(url) 18 titles.extend(temp) 19 temp_class=[key for i in range(len(temp))] 20 categories.extend(temp_class) 21 return True 22 23 for key in url_list.keys(): 24 #按分類分別爬取 25 print("=========正在爬取{}新聞===========".format(key)) 26 #遍歷每個分類中的子連結 27 #首先獲取首頁 28 get_result(url_list[key][0]) 29 #迴圈獲取載入更多得到的頁面 30 for i in range(1,10): 31 try: 32 if get_result(url_list[key][1].format(i)): 33 pass 34 else: 35 continue 36 except: 37 break 38 print("爬取完畢!")
資料合併
1 new=pd.DataFrame({ 2 "新聞內容":titles, 3 "新聞類別":categories 4 }) 5 old=pd.read_csv("新聞資料集.csv",encoding='utf-8',engine='python') 6 def update(old,new): 7 ''' 8 更新資料集:將本次新爬取的資料加入到資料集中(去除掉了重複元素) 9 ''' 10 data=new.append(old) 11 data=data.drop_duplicates() 12 return data 13 print("更新資料集...") 14 df=update(old,new) 15 df.to_csv("新聞資料集.csv",index=None,encoding='gbk') 16 print("更新完畢,共有資料:",df.shape[0],"條") 17 df.head()
2.對資料進行清洗和處理
1 def remove_punctuation(line): 2 line = str(line) 3 if line.strip()=='': 4 return '' 5 rule = re.compile(u"[^a-zA-Z0-9\u4E00-\u9FA5]") 6 line = rule.sub('',line) 7 return line 8 9 def stopwordslist(filepath): 10 stopwords = [line.strip() for line in open(filepath, 'r', encoding="UTF-8").readlines()] 11 return stopwords 12 13 #載入停用詞 14 stopwords = stopwordslist("./stop_words.txt") 15 #刪除除字母,數字,漢字以外的所有符號 16 df['clean_review'] = df['新聞內容'].apply(remove_punctuation) 17 #分詞,並過濾停用詞 18 19 df['cut_review'] = df['clean_review'].apply(lambda x: " ".join([w for w in list(jb.cut(x)) if w not in stopwords])) 20 print("資料預處理完畢!")
4.資料分析與視覺化(例如:資料柱形圖、直方圖、散點圖、盒圖、分佈圖)
1 df.新聞類別.value_counts().plot(kind='bar') 2 plt.title("各個類別新聞爬取數目統計")
1 # 繪製混淆矩陣函式 2 def plot_confusion_matrix(cm, classes, 3 normalize=False, 4 title='Confusion matrix', 5 cmap=plt.cm.Blues): 6 plt.figure(figsize=(8,6)) 7 plt.imshow(cm, interpolation='nearest', cmap=cmap) 8 plt.title(title) 9 plt.colorbar() 10 tick_marks = np.arange(len(classes)) 11 plt.xticks(tick_marks, classes, rotation=45) 12 plt.yticks(tick_marks, classes) 13 14 fmt = '.2f' if normalize else 'd' 15 thresh = cm.max() / 2. 16 for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): 17 plt.text(j, i, format(cm[i, j], fmt), 18 horizontalalignment="center", 19 color="white" if cm[i, j] > thresh else "black") 20 21 plt.tight_layout() 22 plt.ylabel('真實標籤') 23 plt.xlabel('預測標籤') 24 plt.show() 25 class_names=['軍事','國內','國際','科技','航空'] 26 cm= confusion_matrix(y_test, y_pred) 27 title="分類準確率:{:.2f}%".format(accuracy_score(y_test,y_pred)*100) 28 plot_confusion_matrix(cm,classes=class_names,title=title) 29 print("分類評估報告如下:\n") 30 print(classification_report(y_test,y_pred))
5.將以上各部分的程式碼彙總,附上完整程式程式碼
1 import requests 2 import json 3 import re 4 5 import pandas as pd 6 import numpy as np 7 8 from sklearn.naive_bayes import MultinomialNB 9 from sklearn.model_selection import train_test_split 10 from sklearn.metrics import accuracy_score, confusion_matrix,f1_score,classification_report 11 from sklearn.feature_extraction.text import TfidfTransformer 12 from sklearn.feature_extraction.text import TfidfVectorizer 13 14 import jieba as jb 15 import matplotlib.pyplot as plt 16 import itertools 17 plt.rcParams['font.sans-serif']="SimHei" 18 plt.rcParams['axes.unicode_minus']=False 19 import warnings 20 warnings.filterwarnings('ignore') 21 #要爬取的新聞分類地址國內、國際、軍事、航空、科技 22 url_list={'國內':[ 'https://temp.163.com/special/00804KVA/cm_guonei.js?callback=data_callback', 23 'https://temp.163.com/special/00804KVA/cm_guonei_0{}.js?callback=data_callback'], 24 '國際':['https://temp.163.com/special/00804KVA/cm_guoji.js?callback=data_callback', 25 'https://temp.163.com/special/00804KVA/cm_guoji_0{}.js?callback=data_callback'], 26 '軍事':['https://temp.163.com/special/00804KVA/cm_war.js?callback=data_callback', 27 'https://temp.163.com/special/00804KVA/cm_war_0{}.js?callback=data_callback'], 28 '航空':['https://temp.163.com/special/00804KVA/cm_hangkong.js?callback=data_callback&a=2', 29 'https://temp.163.com/special/00804KVA/cm_hangkong_0{}.js?callback=data_callback&a=2'], 30 '科技':['https://tech.163.com/special/00097UHL/tech_datalist.js?callback=data_callback', 31 'https://tech.163.com/special/00097UHL/tech_datalist_0{}.js?callback=data_callback']} 32 33 def parse_class(url): 34 '''獲取分類下的新聞''' 35 req=requests.get(url) 36 text=req.text 37 res=re.findall("title(.*?)\\n",text) 38 #去除不規範的符號 39 for i in range(len(res)): 40 res[i]=re.sub("\'|\"|\:|'|,|","",res[i]) 41 return res 42 titles=[] 43 categories=[] 44 def get_result(url): 45 global titles,categories 46 temp=parse_class(url) 47 if temp[0]=='>網易-404</title>': 48 return False 49 print(url) 50 titles.extend(temp) 51 temp_class=[key for i in range(len(temp))] 52 categories.extend(temp_class) 53 return True 54 55 for key in url_list.keys(): 56 #按分類分別爬取 57 print("=========正在爬取{}新聞===========".format(key)) 58 #遍歷每個分類中的子連結 59 #首先獲取首頁 60 get_result(url_list[key][0]) 61 #迴圈獲取載入更多得到的頁面 62 for i in range(1,10): 63 try: 64 if get_result(url_list[key][1].format(i)): 65 pass 66 else: 67 continue 68 except: 69 break 70 print("爬取完畢!") 71 72 new=pd.DataFrame({ 73 "新聞內容":titles, 74 "新聞類別":categories 75 }) 76 old=pd.read_csv("新聞資料集.csv",encoding='gbk') 77 def update(old,new): 78 ''' 79 更新資料集:將本次新爬取的資料加入到資料集中(去除掉了重複元素) 80 ''' 81 data=new.append(old) 82 data=data.drop_duplicates() 83 return data 84 print("更新資料集...") 85 df=update(old,new) 86 df.to_csv("新聞資料集.csv",index=None,encoding='gbk') 87 print("更新完畢,共有資料:",df.shape[0],"條") 88 df.head() 89 90 def remove_punctuation(line): 91 line = str(line) 92 if line.strip()=='': 93 return '' 94 rule = re.compile(u"[^a-zA-Z0-9\u4E00-\u9FA5]") 95 line = rule.sub('',line) 96 return line 97 98 def stopwordslist(filepath): 99 stopwords = [line.strip() for line in open(filepath, 'r', encoding="UTF-8").readlines()] 100 return stopwords 101 102 #載入停用詞 103 stopwords = stopwordslist("./stop_words.txt") 104 #刪除除字母,數字,漢字以外的所有符號 105 df['clean_review'] = df['新聞內容'].apply(remove_punctuation) 106 #分詞,並過濾停用詞 107 108 df['cut_review'] = df['clean_review'].apply(lambda x: " ".join([w for w in list(jb.cut(x)) if w not in stopwords])) 109 print("資料預處理完畢!") 110 111 df.新聞類別.value_counts().plot(kind='bar') 112 plt.title("各個類別新聞爬取數目統計") 113 114 # 繪製混淆矩陣函式 115 def plot_confusion_matrix(cm, classes, 116 normalize=False, 117 title='Confusion matrix', 118 cmap=plt.cm.Blues): 119 plt.figure(figsize=(8,6)) 120 plt.imshow(cm, interpolation='nearest', cmap=cmap) 121 plt.title(title) 122 plt.colorbar() 123 tick_marks = np.arange(len(classes)) 124 plt.xticks(tick_marks, classes, rotation=45) 125 plt.yticks(tick_marks, classes) 126 127 fmt = '.2f' if normalize else 'd' 128 thresh = cm.max() / 2. 129 for i, j in itertools.product(range(cm.shape[0]), range(cm.shape[1])): 130 plt.text(j, i, format(cm[i, j], fmt), 131 horizontalalignment="center", 132 color="white" if cm[i, j] > thresh else "black") 133 134 plt.tight_layout() 135 plt.ylabel('真實標籤') 136 plt.xlabel('預測標籤') 137 plt.show() 138 class_names=['軍事','國內','國際','科技','航空'] 139 cm= confusion_matrix(y_test, y_pred) 140 title="分類準確率:{:.2f}%".format(accuracy_score(y_test,y_pred)*100) 141 plot_confusion_matrix(cm,classes=class_names,title=title) 142 print("分類評估報告如下:\n") 143 print(classification_report(y_test,y_pred))
五、總結
通過這次設計讓我學會了做一個專案首先得學會進行需求分析,資料分析等。此次主題資料分析與視覺化、可以看出來科技分割槽新聞最少。在這個設計過程中我學習到了許多知識,也對網路爬蟲有了新的認識。但是還有不足之處,我會爭取加以改進的。