做为正在探索如何写做并发表到各大博客平台的新人,目前虽然已基本弄清写做和发表的基本流程,可是离打造我的知名度还差很大很大一段距离.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
文件内容.本文主要介绍的是解决问题的思路,对于其中涉及到的相关技术点并未深刻展开,关键源码已经贴上,若是还想要更详细的完整源码,能够留言回复.