做爲正在探索如何寫做並發表到各大博客平臺的新人,目前雖然已基本弄清寫做和發表的基本流程,可是離打造我的知名度還差很大很大一段距離.java
尤爲處於新手階段,須要的更是自信與外界的積極反饋,看着各平臺日益增加的閱讀量和粉絲量,心中天然不甚欣喜.git
可是,持續的技術輸出可否堅持下去很大程度上靠的是外界的積極反饋,若是寫的文章基本沒人看,或者反映並不理想,估計也很難再堅持創做了.程序員
因此筆者天天晚上都會統計一下各個平臺的數據,看一下有哪些收穫,只有看得見的數據才能給我安全感和自信心.github
下面簡單展現一下每日數據統計效果:apache
這裏列出的平臺默認是沒有提供數據分析功能,而有些平臺已經提供數據分析,說不定還要豐富圖表分析功能,天然不用像下面這般複雜操做.json
因此,針對沒有提供數據分析的平臺,只好採用人工方式進行每日數據統計,一開始文章比較少,用肉眼加計算器就能很輕鬆獲得閱讀量和粉絲數等數據.數組
可是,隨着文章的每日更新,不斷累加的文章愈來愈多,人工方式簡直讓我崩潰,好比昨晚在統計慕課網手記相關數據時就意外被一旁的小侄子打斷三次!安全
簡直不可忍受,窮則思變,懶則想法偷懶,因此是時候探索新的方式解決純手動的弊端了!併發
圖表渲染效果來自
gitbook
的chart
插件,詳情請參考 官網文檔maven
要想解放重複勞動量,必須先知道問題瓶頸,如今先回顧一下手動操做流程.
chart
插件渲染圖標.chart
渲染數據語法,截圖渲染效果.github
網站原本沒必要利用截圖表示圖表的,只是無奈
github
不支持chart
插件語法,只好用截圖代替了.
分析上述流程後不難發現,最複雜也是最費時費力的即是第二步的數據統計,因爲要肉眼統計文章並用計算器累加,簡直是手腦並用,只有高度專一才能保證統計數據的準確性和可靠性.
這也就解釋了被打斷三次後的崩潰了,找到問題的根源了,想辦法如何解決吧!
最容易想到的解決辦法是手動複製文章列表數據,而後程序分析提取關鍵數據,最後再統計數據.
又是三步操做,再分解一下步驟,看看目前可以解決哪部分.
在這三步中,只有第二步最爲關鍵,也是目前我能作到的事情,由於第一步可能須要爬蟲技術或模擬接口調用,整體來講,整體來講仍是比較麻煩的,之後再繼續優化吧.
所以,如今先着手如何將複製後的文章列表轉化成程序可以處理的文件格式,進而調用程序統計.
下面以慕課網手記文章爲例,簡單介紹下處理流程.
如今文章已複製到文件,應該保存成什麼格式呢?這又是一個思考點.
因爲文件內容最終須要被程序處理,而程序處理要求數據須要具有必定的格式,所以天然不能是 txt
或 word
這類文檔,日常接觸比較多的文檔數據處理通常就是 excel
或者 json
類型的文檔.
這裏須要 excel
這種格式文檔,可是 excel
比較笨重,還須要相關軟件才能打開 excel
文件,好像並非很適合,怎麼辦呢?
可是我真的須要這種一行一行的數據格式啊,有沒有折中的處理方案?
固然有!輕量級的 csv
格式不是巧合適合簡單文檔處理嗎?
csv
和 excel
具備相似的特徵,大致上都是一行一行一列一列地存儲數據,最適合統計數據了.
看着亂七八糟的文章列表,csv
也沒法處理這種複雜數據啊,接下來仍是要手動格式化數據,整理一下數據.
至此,咱們已經完成數據分析的第一步了,接下來是如何讀取 csv
文件,因爲本人是 java
程序員,因此我要看一下 java
如何處理 csv
文件.
需求很簡單,編寫一個 csv
工具類並實現基本的寫入和讀取操做便可.
說到工具類固然首選現成的開源工具了,畢竟小小的需求不值得造輪子.
說到開源工具,腦海中第一個閃現的是 Apache Commons
工具類,因此先去 maven
上搜一下有沒有 csv
相關的工具類.
天不負我!果真有 csv
相關工具類,下面就開始研究如何調用吧!
commons-csv
工具類<!-- https://mvnrepository.com/artifact/org.apache.commons/commons-csv --> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-csv</artifactId> <version>1.6</version> </dependency>
/** * 寫入csv文件 * * @param data 數據內容 * @param filePath 文件路徑 * @throws IOException **/ public static void writeCsv(List<String[]> data, String filePath) throws IOException { FileWriter fw = new FileWriter(new File(filePath)); final CSVPrinter printer = CSVFormat.EXCEL.print(fw); printer.printRecords(data); printer.flush(); printer.close(); } /** * 讀取csv文件 * * @param filePath 文件路徑 * @return CSVRecord 迭代對象 * @throws IOException **/ public static Iterable<CSVRecord> readCSV(String filePath) throws IOException { InputStream inputStream = new FileInputStream(filePath); InputStreamReader isr = new InputStreamReader(inputStream); Iterable<CSVRecord> records = CSVFormat.EXCEL.parse(isr); return records; } /** * 測試寫入並讀取csv 文件 */ private static void testWriteAndRead() throws IOException { //寫入數據 List<String[]> data = new ArrayList<String[]>(); data.add(new String[]{"張三", "18", "3000"}); data.add(new String[]{"李四", "20", "4000"}); data.add(new String[]{"王二", "25", "5000"}); //寫入文件路徑 String path = "/Users/sunpo/Downloads/testWriteAndRead.csv"; //寫入 csv 文件 writeCsv(data, path); //讀取文件 Iterable<CSVRecord> records = readCSV(path); for (CSVRecord record : records) { for (String string : record) { System.out.print(string); System.out.print(" "); } System.out.println(); } }
測試結果然實可用,工具類基本功能編寫完成.
已經有了 csv
工具類,那麼如今就要想辦法解決實際問題,再看一下當前慕課網手記的內容格式吧!
148瀏覽 2推薦 0評論 204瀏覽 2推薦 0評論 181瀏覽 2推薦 0評論
分析上述內容格式有如下特色:
按照上述分析結果,開始 coding
逐個解決,下面展現下關鍵代碼.
List<String> row = StringTools.splitToListString(string, " ");
StringTools.splitToListString
方式是筆者封裝的分割字符串方法,目的將字符串按照指定分隔符分割成字符串列表
String readCountWithDescString = row.get(0); String readCountString = StringUtils.substringBefore(readCountWithDescString, "瀏覽"); String recommendCountWithDescString = row.get(1); String recommendCountString = StringUtils.substringBefore(recommendCountWithDescString, "推薦"); String commentCountWithDescString = row.get(2); String commentCountString = StringUtils.substringBefore(commentCountWithDescString, "評論");
StringUtils.substringBefore
方法也是Apache Commons
工具類,具體來源於org.apache.commons.lang3
,下述涉及到的StringUtils
靜態方法 也是,再也不單獨說明.
//瀏覽數 int readCount = 0; //推薦數 int recommendCount = 0; //評論數 int commentCount = 0; readCount += Integer.parseInt(readCountString); recommendCount += Integer.parseInt(recommendCountString); commentCount += Integer.parseInt(commentCountString);
如此一來,三步均已解決,如今運行如下統計方法,看一下真實效果如何.
/** * 統計慕課手記 * * @throws IOException */ private static void countImooc() throws IOException { //昨日統計數據 String yesterday = DateFormatUtils.format(DateUtils.addDays(new Date(), -1), "yyyyMMdd"); String path = String.format("/Users/sunpo/Documents/workspace/count/imooc-%s.csv", yesterday); //總行數 int allRows = 0; //有效行數 int allValidRows = 0; //當前行是否有效 boolean isValidRow = true; //瀏覽數 int readCount = 0; //推薦數 int recommendCount = 0; //評論數 int commentCount = 0; Iterable<CSVRecord> records = readCSV(path); for (CSVRecord record : records) { allRows++; for (String string : record) { System.out.println(string); if (StringUtils.isBlank(string)) { isValidRow = false; break; } List<String> row = StringTools.splitToListString(string, " "); String readCountWithDescString = row.get(0); String readCountString = StringUtils.substringBefore(readCountWithDescString, "瀏覽"); String recommendCountWithDescString = row.get(1); String recommendCountString = StringUtils.substringBefore(recommendCountWithDescString, "推薦"); String commentCountWithDescString = row.get(2); String commentCountString = StringUtils.substringBefore(commentCountWithDescString, "評論"); readCount += Integer.parseInt(readCountString); recommendCount += Integer.parseInt(recommendCountString); commentCount += Integer.parseInt(commentCountString); } if (isValidRow) { allValidRows++; } isValidRow = true; } System.out.println(); System.out.println(String.format("[慕課手記] 一共讀取%d行,有效行: allValidRows = %d ,其中瀏覽數: readCount = %d ,推薦數: recommendCount = %d ,評論數: commentCount = %d", allRows, allValidRows, readCount, recommendCount, commentCount)); System.out.println(); }
很完美,終於沒必要再肉眼統計數據了,雖然很長程度上仍然依賴人工整理好 csv
文件,可是目前已經解決了純手動的弊端.
所以,上述解決方案是半手動的方式,仍然還有不少能夠優化的地方,等下次忍受不了這種方案時再解決!
本文主要介紹了純手工統計報表遇到的諸多問題,尋求一種相對簡單的解決方案.
基本流程大體能夠分爲下述流程:
csv
格式文件.csv
工具處理類,解析並統計 csv
文件內容.本文主要介紹的是解決問題的思路,對於其中涉及到的相關技術點並未深刻展開,關鍵源碼已經貼上,若是還想要更詳細的完整源碼,能夠留言回覆.