唐诗分析项目设计文档
文章目錄
- 一. 唐詩項目介紹
- 1.1項目背景
- 1.2項目需求
- 1.3項目設(shè)計
- 1.4項目工具選擇
- 二.唐詩數(shù)據(jù)爬取模塊
- 2.1技術(shù)選型環(huán)節(jié)
- 2.1.1爬蟲技術(shù)
- 2.1.2分詞技術(shù)
- 2.2項目依賴環(huán)節(jié)
- 2.3預研環(huán)節(jié)
- 2.3.1解析列表頁Demo
- 2.3.2分詞Demo
- 2.4具體開發(fā)環(huán)節(jié)
- 2.4.1數(shù)據(jù)庫的設(shè)計
- 2.4.2爬取,解析數(shù)據(jù)
- 2.4.3數(shù)據(jù)寫入到數(shù)據(jù)庫中
- 2.4.4驗證并優(yōu)化---多線程
- 2.5總結(jié)問題
- 三.詩詞可視化分析模塊
- 3.1技術(shù)選型
- 3.1.1 echarts可視化
- 3.1.2 jquery的發(fā)起ajax請求
- 3.1.3 FastJson格式
- 3.2導入依賴
- 3.3代碼開發(fā)
- 3.3.1 JDBC建立數(shù)據(jù)庫連接
- 3.3.2 整理詩的數(shù)量
- 3.3.3 整理分詞
- 3.4驗證效果
一. 唐詩項目介紹
1.1項目背景
爬蟲技術(shù)一直處于風口浪尖,爬了不該爬的會引來一身官司,爬想爬取的數(shù)據(jù)又不會輕而易舉獲得,但是又想來玩玩爬蟲技術(shù),怎么辦呢?首選古詩文網(wǎng),因為據(jù)了解它是沒有設(shè)置任何反爬蟲機制的,數(shù)據(jù)都是公開合法的,這里我就選擇了唐詩三百首來進行爬蟲,你們不好奇哪位唐代詩人寫的詩最多嗎?你們不好奇詩人們最喜歡用什么詞去作詩嗎?如果你對唐詩也感興趣,那就跟我一起開啟這個奇妙的詩詞探險吧。
1.2項目需求
一.用柱狀圖來展示詩人們的姓名和詩詞數(shù)量,并按詩詞數(shù)量降序排序。
二.用詞云來展示詞的使用頻度,使用最頻繁的詞應該一眼看出。
1.3項目設(shè)計
一.通過爬蟲機制把唐詩的數(shù)據(jù)爬取出來,對它進行解析,將每首詩的數(shù)據(jù)寫入到數(shù)據(jù)庫中。
二.通過發(fā)起請求來對數(shù)據(jù)進行分析篩選,最后渲染成可視化效果。
1.4項目工具選擇
這是一個Web項目,Java選擇用IDEA這個編譯器,選擇用maven來引進一些需要用到的第三方庫,通過tomcat這個Web應用服務器來執(zhí)行。
二.唐詩數(shù)據(jù)爬取模塊
2.1技術(shù)選型環(huán)節(jié)
2.1.1爬蟲技術(shù)
我了解到的爬蟲技術(shù)棧有 HtmlUnit,HttpClient,這里我選擇了HtmlUnit這個框架。
- 原因:HttpClient是用來模擬HTTP請求的,用的是socket通信,通過get方法來提交請求,只能獲取html靜態(tài)頁面的源碼,如果頁面中有js部分,則不能獲取到j(luò)s執(zhí)行后的源碼。
HtmlUnit是一款無界面的瀏覽器程序庫,它模擬用戶去操作瀏覽器,允許調(diào)用頁面,填寫表單,點擊鏈接等,還可以執(zhí)行js,有很多的API用起來也非常方便。
2.1.2分詞技術(shù)
使用ansj_seg庫對古詩的標題和正文進行分詞,為詞云做準備。這個中文分詞器正確率高,不容易出做,分詞速度也快,效果也比較高。
2.2項目依賴環(huán)節(jié)
解析請求html頁面
<dependency><groupId>net.sourceforge.htmlunit</groupId><artifactId>htmlunit</artifactId><version>2.36.0</version></dependency>分詞
<dependency><groupId>org.ansj</groupId><artifactId>ansj_seg</artifactId><version>5.1.6</version></dependency>2.3預研環(huán)節(jié)
通過編寫一些Demo來熟悉這些技術(shù)的使用,看看它展示的效果是否滿意。
2.3.1解析列表頁Demo
WebClient client = new WebClient(BrowserVersion.CHROME);client.getOptions().setJavaScriptEnabled(false);client.getOptions().setCssEnabled(false);String baseurl = "https://so.gushiwen.org";String pathurl = "/gushi/tangshi.aspx";List<String> detailUrlList = new ArrayList<>();//所有古詩的詳情頁的url//列表頁的解析{String url = baseurl + pathurl;HtmlPage page = client.getPage(url);//獲取詩詞頁面List<HtmlElement> divs = page.getBody().getElementsByAttribute("div", "class", "typecont");for (HtmlElement div : divs) {List<HtmlElement> as = div.getElementsByTagName("a");for (HtmlElement a : as) {String detailUrl = a.getAttribute("href");detailUrlList.add(baseurl + detailUrl);}}}2.3.2分詞Demo
public static void main(String[] args) {String sentence="中華人民共和國成立了!中國人民從此站起來了";List<Term> termlist=NlpAnalysis.parse(sentence).getTerms();for(Term term:termlist){System.out.println(term.getNatureStr()+":"+term.getRealName());}}2.4具體開發(fā)環(huán)節(jié)
2.4.1數(shù)據(jù)庫的設(shè)計
數(shù)據(jù)庫要存取:自增主鍵id,標題,朝代,作者,正文,分詞,sha-256。
- SHA-256是為了防止下載重復詩詞,所以用每首詩的標題和正文去計算SHA-256值。
2.4.2爬取,解析數(shù)據(jù)
- 獲取列表頁解析出每首詩的url
- 解析詳情頁得出要往數(shù)據(jù)庫中寫入的數(shù)據(jù)(標題,朝代,作者,正文,計算SHA-256,計算分詞(切記分詞要去除特殊字符,比如符號,null等)需要將分詞拼接成字符串格式,方便存儲)
2.4.3數(shù)據(jù)寫入到數(shù)據(jù)庫中
- 通過JDBC建立數(shù)據(jù)庫連接,將標題,朝代等信息插入到數(shù)據(jù)庫的表中。
2.4.4驗證并優(yōu)化—多線程
*通過sql語句查看320首詩詞數(shù)據(jù)是否成功寫入到數(shù)據(jù)庫中。如果信息無誤,則插入成功。
- 單線程版本效率低,每次都是主線程去完成各項任務,在解析詳情頁的時候每次都是主線程,而總共有320首詩,就要挨個去解析320次,非常耗時。
- 引入多線程版本:讓主線程去獲取列表頁,解析列表頁,得出每首詩的url,開啟多個線程,去完成列表頁解析工作,并將數(shù)據(jù)寫入到數(shù)據(jù)庫中。
問題:1.webclient不是線程安全的,每個線程都得自己建一個webclient對象
2.connection不是線程安全的,需要通過傳
datasource這個參數(shù)去建立連接。
3.MessageDigest這個計算SHA-256的也不是線程安全的。
多線程每次都要創(chuàng)建320個子線程去執(zhí)行任務,執(zhí)行完再銷毀,顯然有點浪費資源。 - 線程池版本:這里用的是Executors.newFixedThreadPool(30)這個固定數(shù)目的線程池,把多線程要處理的那些任務去交給線程池里面的線程去完成,這里我設(shè)置的是30個核心線程。
BUG: JVM結(jié)束是指所有非后臺線程執(zhí)行結(jié)束后才關(guān)閉,而線程池一直在主線程中,根本不可能自己關(guān)閉,它會不斷地去執(zhí)行任務,重復的死循環(huán),永不停止。
解決辦法: 只要等所有子線程都完成任務,就可以手動關(guān)閉線程池。 - 如何判斷子線程任務是都都結(jié)束了呢?
1.CAS原子類
2.CountDownLatch:開始會設(shè)定要等待的線程數(shù),主線程阻塞,每執(zhí)行完一個子線程就調(diào)用countDown(),此時計數(shù)器-1,直到計時器為0時才將主線程喚醒,不為0 就一直await(),為0說明子線程任務都執(zhí)行完了,就可以關(guān)閉線程池了。
CountDownLatch countDownLatch = new CountDownLatch(detailUrlList.size());//指定countDownLatch要等待的線程數(shù)for (String url : detailUrlList) {pool.execute(new Job(url,dataSource2,countDownLatch));}countDownLatch.await();//如果沒處理結(jié)束,就等待pool.shutdown();//最后關(guān)閉線程池}2.5總結(jié)問題
- 在創(chuàng)建數(shù)據(jù)庫的時候,要合理的設(shè)計每個字段的類型,不能盲目浪費資源。
- 多線程設(shè)計,一定要考慮線程安全問題,不然出大錯。
- 學會不斷地優(yōu)化項目。
三.詩詞可視化分析模塊
3.1技術(shù)選型
3.1.1 echarts可視化
echarts是一個開源免費的javascript可視化庫,柱狀圖和詞云都是來自于它。而且它是開源的,中文文檔,方便上手。
3.1.2 jquery的發(fā)起ajax請求
因為echarts的數(shù)據(jù)是寫死的,所以使用jquery來發(fā)起ajax請求,用httpservlet來處理請求,返回一個json格式的字符串,等加載成功執(zhí)行success方法去進行可視化,這樣數(shù)據(jù)就是從請求響應獲取的,不再是寫死的。
3.1.3 FastJson格式
返回Json格式的第三方庫有很多,比如Gson,FastJson等,我選擇FastJson主要是因為寫起來簡單,是阿里巴巴維護的,我這個應用小,也估計碰不到它的BUG。
3.2導入依賴
<dependency><groupId>com.alibaba</groupId><artifactId>fastjson</artifactId><version>1.2.62</version></dependency><dependency><groupId>javax.servlet</groupId><artifactId>javax.servlet-api</artifactId><version>3.1.0</version><scope>provided</scope></dependency>3.3代碼開發(fā)
3.3.1 JDBC建立數(shù)據(jù)庫連接
這里用的是餓漢的設(shè)計模式,來進行數(shù)據(jù)庫連接。
3.3.2 整理詩的數(shù)量
- 繼承HttpServlet,通過doGet方法來處理ajax發(fā)起的http請求,用復合查詢sql語句就可以搞定,再將數(shù)據(jù)寫入到JSONArray中,返回一個Json格式的字符串。
- 用@WebServlet(“rank.json”)來配置path路徑,就不需要去web.xml去配置servlet了。
- 發(fā)起ajax請求,收到響應后去執(zhí)行success里面的方法,進行柱狀圖的渲染。
通過html頁面的script標簽找到j(luò)s文件去執(zhí)行。
3.3.3 整理分詞
- 繼承HttpServlet,通過doGet方法處理請求,將分詞都先放入到list中,再用map來整理每個詞出現(xiàn)的次數(shù),最后將Key和Value來放入到JSONArray中,返回一個json格式的字符串。
- 同樣用@WebServlet("/words.json")
3.4驗證效果
總結(jié)
以上是生活随笔為你收集整理的唐诗分析项目设计文档的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 《图解HTTP》第一章个人学习思考
- 下一篇: [批量重命名工具] 批量图片识别文字来命