日期:2020.02.02
博客期:141
星期日
【本博客的代碼如若要使用,請在下方評論區留言,之后再用(就是跟我說一聲)】
所有相關跳轉:
a.【簡單准備】
b.【雲圖制作+數據導入】
c.【拓撲數據】
d.【數據修復】
e.【解釋修復+熱詞引用】(本期博客)
f.【JSP演示+頁面跳轉】
g.【熱詞分類+目錄生成】
h.【熱詞關系圖+報告生成】
i . 【App制作】
j . 【安全性改造】
嗯~昨天相當於把數據重新爬了一邊,但是貌似數據仍然不合適。問題到底出在什么地方呢?我直接回答了吧!如果我們的需求僅僅是雲圖展示,那么這些數據就夠用了,甚至還多,因為任務是要實現“標記熱詞出現在哪個新聞里”,這就需要我們記錄一下標題。當然!這也不難實現。我先把我所有的 Python 類全部單獨分包做成一個.py文件。然后,我將數據庫文件重新配置,將sql文件覆蓋到上一篇博客中(本篇博客也會發出下載鏈接)。然后找到之前的添加解釋的類,進行二次利用,重新爬取!這個任務也做完了以后呢,我會把之前的鏈接分別對應到每一個熱詞,利用 jsp 技術實現熱詞相關信息的展示。最后,將探索一下熱詞之間的緊密程度(說實在的我現在有點兒不太理解這是什么意思,等睡一覺,起來問了老師,再修改本篇博客),利用 ECharts 接口制作可供展示的關系圖,努力肝了一天發現只做到了展示,沒能完成熱詞關系探索,嗯,交給今后的我了。
1、整理文件(修改之前的 爬取網頁的 文件 不再 撰寫)
嗯,現在我已經將文件規整好了,如下圖。先說一下,改造以后的python代碼將每一個類分別單獨封裝成一個.py文件,每一個執行過程將單獨使用一個.py文件,並放入到 itWords.process 包當中!我想過可以將所有執行過程寫到一個.py文件里,但這樣的話就有點兒亂,最終還是決定分開寫。
itWords.basic 包:
此包類已經被整合,詳細參照博客: Python 爬取的類封裝【將來可能會改造,持續更新...】(2020年寒假小目標09)
itWords.bean 包:

1 import codecs 2 3 4 class KeyWords: 5 # 熱詞 6 word = "" 7 # 對應鏈接 8 link = "" 9 # 頻數 10 num = 0 11 12 def __init__(self,word,link,num): 13 self.word = word 14 self.link = link 15 self.num = num 16 17 # 整理成 一行 字符串 18 def __toString__(self): 19 return self.word +"\t"+str(self.num)+"\t"+self.link 20 21 # 將 自動整理好的字符串 帶換行符 追加 到文件后 22 def __toFile__(self,filePath): 23 f = codecs.open(filePath, "a+", 'utf-8') 24 f.write(self.__toString__() + "\n") 25 f.close()

1 import codecs 2 3 4 class News: 5 # 標題 6 title = "" 7 # 內容 8 info = "" 9 # 鏈接 10 link = "" 11 12 # 初始化 13 def __init__(self,title,info,link): 14 self.title = title 15 self.info = info 16 self.link = link 17 18 # 整理成 一行 字符串 19 def __toString__(self): 20 return self.link+"\t"+self.title+"\t"+self.info 21 22 # 將 自動整理好的字符串 帶換行符 追加 到文件后 23 def __toFile__(self,filePath): 24 f = codecs.open(filePath, "a+", 'utf-8') 25 f.write(self.__toString__() + "\n") 26 f.close() 27 28 # 將 標題和內容 銜接的 字符串 予以返回 ( 計算詞語頻率 ) 29 def getSimple(self): 30 return self.title+self.info
itWords.process 包:

1 import codecs 2 3 4 def makeSql(): 5 file_path = "../../testFile/rc/words_sql.txt" 6 f = codecs.open(file_path, "w+", 'utf-8') 7 f.write("") 8 f.close() 9 10 fw = open("../../testFile/rc/news.txt", mode='r', encoding='utf-8') 11 tmp = fw.readlines() 12 13 num = tmp.__len__() 14 15 for i in range(0,num): 16 group = tmp[i].split("\t") 17 group[0] = "'" + group[0] + "'" 18 group[2] = "'" + group[2][0:group[2].__len__()-1] + "'" 19 f = codecs.open(file_path, "a+", 'utf-8') 20 f.write("Insert into words values ("+group[0]+","+group[1]+","+group[2]+");"+"\n") 21 f.close() 22 23 24 def makeOne(): 25 file_path = "../../testFile/rc/keyword_moreinfo.txt" 26 fw = open("../../testFile/rc/keywords.txt", mode='r', encoding='utf-8') 27 tmp = fw.readlines()
itWords 包:

1 import jieba 2 import jieba.analyse 3 4 5 # 新聞段落高頻詞分析器 6 class ToolToMakeHighWords: 7 # 要處理的字符串 8 test_str = "" 9 10 # 初始化 11 def __init__(self,test_str): 12 self.test_str = str(test_str) 13 pass 14 15 # 使用 文件 建立數據 16 def buildWithFile(self,filePath,type): 17 file = open(filePath, encoding=type) 18 self.test_str = file.read() 19 20 # 直接給予 字符串 建立 21 def buildWithStr(self,test_str): 22 self.test_str = test_str 23 pass 24 25 # 統計詞 26 def getWords(self,isSimple,isAll): 27 if(isSimple): 28 words = jieba.lcut_for_search(self.test_str) 29 return words 30 else: 31 # True - 全模式 , False - 精准模式 32 words = jieba.cut(self.test_str, cut_all=isAll) 33 return words 34 35 # 統計詞頻並排序 36 def getHighWords(self,words): 37 data = {} 38 for charas in words: 39 if len(charas) < 2: 40 continue 41 if charas in data: 42 data[charas] += 1 43 else: 44 data[charas] = 1 45 46 data = sorted(data.items(), key=lambda x: x[1], reverse=True) # 排序 47 48 return data 49 50 # 獲取 前 num 名的高頻詞 ( 帶頻率 ) 51 def selectObjGroup(self,num): 52 a = jieba.analyse.extract_tags(self.test_str, topK=num, withWeight=True, allowPOS=()) 53 return a 54 55 # 獲取 前 num 名的高頻詞 ( 不帶頻率 ) 56 def selectWordGroup(self,num): 57 b = jieba.analyse.extract_tags(self.test_str, topK=num, allowPOS=()) 58 return b

1 import parsel 2 from urllib import request 3 import codecs 4 5 from itWords.bean.KeyWords import KeyWords 6 from itWords.Oranpick import Oranpick 7 8 # [ 連續網頁爬取的對象 ] 9 from itWords.ToolToMakeHighWords import ToolToMakeHighWords 10 11 12 class Surapity: 13 page = 1 14 headers = { 15 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36'} 16 basicURL = "" 17 oran = "" 18 19 # ---[定義構造方法] 20 def __init__(self): 21 self.page = 1 22 self.basicURL = "https://news.cnblogs.com/" 23 self.oran = Oranpick("https://start.firefoxchina.cn/") 24 25 def __close__(self): 26 self.oran.__close__() 27 28 def __next__(self): 29 self.page = self.page + 1 30 self.basicURL = 'https://news.cnblogs.com/n/page/'+str(self.page)+'/' 31 32 # 獲取 url 的內部 HTML 代碼 33 def getHTMLText(self): 34 req = request.Request(url=self.basicURL, headers=self.headers) 35 r = request.urlopen(req).read().decode() 36 return r 37 38 # 獲取頁面內的基本鏈接 39 def getMop(self,filePath): 40 index_html = self.getHTMLText() 41 index_sel = parsel.Selector(index_html) 42 links = index_sel.css(".news_entry a::attr(href)").extract() 43 size = links.__len__() 44 for i in range(0,size): 45 link = "https://news.cnblogs.com"+links[i] 46 self.oran.__reset__(link) 47 news = self.oran.getNews() 48 ttm = ToolToMakeHighWords(news.getSimple()) 49 words = ttm.getHighWords(ttm.getWords(False,False)) 50 leng = words.__len__() 51 # 頻數 要在 15次 以上 52 for i in range(0,leng): 53 if words[i][1]<=15: 54 break 55 keyw = KeyWords(word=words[i][0],link=link,num=words[i][1]) 56 keyw.__toFile__(filePath)

1 import parsel 2 import time 3 from selenium import webdriver 4 5 from itWords.basic import StrSpecialDealer 6 from itWords.bean import News 7 8 9 # [ 一次性網頁爬取的對象 ] 10 11 12 class Oranpick: 13 basicURL = "" 14 profile = "" 15 16 # ---[定義構造方法] 17 def __init__(self, url): 18 self.basicURL = url 19 self.profile = webdriver.Firefox() 20 self.profile.get("https://account.cnblogs.com/signin?returnUrl=https%3A%2F%2Fnews.cnblogs.com%2Fn%2F654191%2F") 21 self.profile.find_element_by_id("LoginName").send_keys("youraccount") 22 self.profile.find_element_by_id("Password").send_keys("yourpassword") 23 time.sleep(2) 24 self.profile.find_element_by_id("submitBtn").click() 25 # 給予 15s 的驗證碼人工驗證環節 26 time.sleep(15) 27 self.profile.get(url) 28 29 # 重新設置 30 def __reset__(self,url): 31 self.basicURL = url 32 self.profile.get(url) 33 34 # ---[定義釋放方法] 35 def __close__(self): 36 self.profile.quit() 37 38 # 獲取 url 的內部 HTML 代碼 39 def getHTMLText(self): 40 a = self.profile.page_source 41 return a 42 43 # 獲取基本數據 44 def getNews(self): 45 index_html = self.getHTMLText() 46 index_sel = parsel.Selector(index_html) 47 context = index_sel.css('#news_title a')[0].extract() 48 context = StrSpecialDealer.getReaction(context) 49 context = StrSpecialDealer.simpleDeal(context) 50 conform = index_sel.css('#news_body')[0].extract() 51 conform = StrSpecialDealer.deleteRe(conform) 52 conform = StrSpecialDealer.simpleDeal(conform) 53 news = News(title=context, info=conform, link=self.basicURL) 54 return news
整理完成,接下來還會改代碼的,上面的 basic 包應該是不會改了。
2、重寫 Bean 相關的基礎類,並重新爬取(可記錄標題)
需要將表示 標題 的 title 屬性加到 KeyWords 類中,並修改 init 初始化方法 和 toString 轉性方法:

1 import codecs 2 3 4 class KeyWords: 5 # 熱詞 6 word = "" 7 # 對應鏈接 8 link = "" 9 # 頻數 10 num = 0 11 # 鏈接標題 12 title = "" 13 14 def __init__(self,word,link,num,title): 15 self.word = word 16 self.link = link 17 self.num = num 18 self.title = title 19 20 # 整理成 一行 字符串 21 def __toString__(self): 22 return self.word +"\t"+str(self.num)+"\t"+self.title+"\t"+self.link 23 24 # 將 自動整理好的字符串 帶換行符 追加 到文件后 25 def __toFile__(self,filePath): 26 f = codecs.open(filePath, "a+", 'utf-8') 27 f.write(self.__toString__() + "\n") 28 f.close()
之后找到引用 KeyWords 的地方,也就是 Surapity 類的 getMop() 方法,將 keyw = KeyWords(word=words[i][0],link=link,num=words[i][1]) 一句改成
keyw = KeyWords(word=words[i][0],link=link,num=words[i][1],title=news.title) ,修改完成后:

1 import parsel 2 from urllib import request 3 import codecs 4 5 from itWords.bean.KeyWords import KeyWords 6 from itWords.Oranpick import Oranpick 7 8 # [ 連續網頁爬取的對象 ] 9 from itWords.ToolToMakeHighWords import ToolToMakeHighWords 10 11 12 class Surapity: 13 page = 1 14 headers = { 15 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36'} 16 basicURL = "" 17 oran = "" 18 19 # ---[定義構造方法] 20 def __init__(self): 21 self.page = 1 22 self.basicURL = "https://news.cnblogs.com/" 23 self.oran = Oranpick("https://start.firefoxchina.cn/") 24 25 def __close__(self): 26 self.oran.__close__() 27 28 def __next__(self): 29 self.page = self.page + 1 30 self.basicURL = 'https://news.cnblogs.com/n/page/'+str(self.page)+'/' 31 32 # 獲取 url 的內部 HTML 代碼 33 def getHTMLText(self): 34 req = request.Request(url=self.basicURL, headers=self.headers) 35 r = request.urlopen(req).read().decode() 36 return r 37 38 # 獲取頁面內的基本鏈接 39 def getMop(self,filePath): 40 index_html = self.getHTMLText() 41 index_sel = parsel.Selector(index_html) 42 links = index_sel.css(".news_entry a::attr(href)").extract() 43 size = links.__len__() 44 for i in range(0,size): 45 link = "https://news.cnblogs.com"+links[i] 46 self.oran.__reset__(link) 47 news = self.oran.getNews() 48 ttm = ToolToMakeHighWords(news.getSimple()) 49 words = ttm.getHighWords(ttm.getWords(False,False)) 50 leng = words.__len__() 51 # 頻數 要在 15次 以上 52 for i in range(0,leng): 53 if words[i][1]<=15: 54 break 55 keyw = KeyWords(word=words[i][0],link=link,num=words[i][1],title=news.title) 56 keyw.__toFile__(filePath)
之后,在 process 編寫 過程文件 paData.py 重新爬取

1 from itWords.Surapity import Surapity 2 from itWords.basic.StringWriter import StringWriter 3 4 5 def main(): 6 filepath = "../../testFile/rc/news.txt" 7 s = Surapity() 8 StringWriter(filepath).makeFileNull() 9 s.getMop(filepath) 10 s.__next__() 11 s.getMop(filepath) 12 while s.page <= 100: 13 s.__next__() 14 s.getMop(filepath) 15 s.__close__() 16 17 18 main()
爬取得到結果如下:
3、簡單的數據導入(附帶sql文件)
在MySql中,重新建立 words 表:
准備 Insert 語句,修改 fileR.py ,並執行:

1 import codecs 2 3 4 def makeSql(): 5 file_path = "../../testFile/rc/words_sql.txt" 6 f = codecs.open(file_path, "w+", 'utf-8') 7 f.write("") 8 f.close() 9 10 fw = open("../../testFile/rc/news.txt", mode='r', encoding='utf-8') 11 tmp = fw.readlines() 12 13 num = tmp.__len__() 14 15 for i in range(0,num): 16 group = tmp[i].split("\t") 17 group[0] = "'" + group[0] + "'" 18 group[3] = "'" + group[3][0:group[3].__len__()-1] + "'" 19 f = codecs.open(file_path, "a+", 'utf-8') 20 f.write("Insert into words values ("+group[0]+","+group[1]+",'"+group[2]+"',"+group[3]+");"+"\n") 21 f.close() 22 23 makeSql()
之后,進入數據庫,選擇新建查詢,輸入 testFile/rc/words_sql.txt 文件內的sql語句,並予以執行
使用上次建視圖的代碼重新建立視圖(也可以建成新表)名稱:keywords,如圖:
Sql 文件下載地址:https://files.cnblogs.com/files/onepersonwholive/words.zip
4、解釋修復——重新利用 百度百科 進行解釋性文字爬取
先使用 Navicat 導出 keywords 表,設置 \t 為列間隔,\n 為行間隔,導出 txt 文件(不要文本限定符)
之后,將此文件剪切到 testFile/rc/keywords.txt 處
編寫新的Bean類 ExplainThings:

1 class ExplainThings: 2 # --- [ 方法域 ] 3 # 初始化 4 def __init__(self,word,exp,num): 5 self.word = word 6 self.num = num 7 self.exp = exp 8 9 # 整理成 一行 字符串 10 def __toString__(self): 11 return self.word + "\t" + str(self.num) + "\t" + self.exp 12 13 # 整理成 Insert 語句 14 def __toSql__(self): 15 return "Insert into keywords VALUES ('"+self.word+"',"+str(self.num)+",'"+self.exp+"');" 16 17 # --- [ 屬性域 ] 18 # 熱詞 19 word = "" 20 # 解釋 21 exp = "" 22 # 頻數 23 num = 0
之后將老代碼,進行整合和修改

1 from itWords.WebConnector import WebConnector 2 from itWords.basic.StrSpecialDealer import StrSpecialDealer 3 from itWords.basic.StringWriter import StringWriter 4 from itWords.bean.ExplainThings import ExplainThings 5 6 wc = WebConnector() 7 sw = StringWriter("../../testFile/rc/moreinfo.txt") 8 9 sw.makeFileNull() 10 11 fw = open("../../testFile/rc/keywords.txt", mode='r', encoding='utf-8') 12 lines = fw.readlines() 13 14 num = lines.__len__() 15 print(num) 16 for i in range(0, num): 17 print(str(i)) 18 str_line = lines[i] 19 gr = str_line.split("\t") 20 name_b = StrSpecialDealer.simpleDeal(gr[0]) 21 num_b = StrSpecialDealer.simpleDeal(gr[1]) 22 wc.__reset__() 23 wc.getMore(name_b) 24 more_b = wc.getFirstChanel() 25 ex = ExplainThings(word=name_b,exp=more_b,num=num_b) 26 sw.write(ex.__toSql__()) 27 28 wc.__close__()
爬取得到Insert數據以后,將keywords表刪掉(或視圖),新建 keywords表,將 Insert文件執行一邊
最終得到數據,如圖所示:
5、jsp實現熱詞的信息展示(附帶 按照 詞頻或熱詞拼寫 的 順序或逆序 排序)——先顯示單頁30條數據
緊趕慢趕,寫了展示部分,這還需要進一步的改造,今天時間不多了,還要抓緊時間趕另一項任務呢!
先設置每一頁30個數據,數據橫向顯示好像有點兒不妥,豎向感覺也不太合適啊!頁面跳轉交給明天的我來寫。
6、將鏈接寫到每一個對應熱詞當中去
實現了點擊 “詳細信息”鏈接可以跳轉頁面至單個熱詞的頁面
總算是在2月3號以前寫完了,呼!明天整理頁面的問題!