關於寫作那些事之終於還是無法忍受純人工統計資料

雪之夢技術驛站發表於2019-04-11

背景

作為正在探索如何寫作並發表到各大部落格平臺的新人,目前雖然已基本弄清寫作和發表的基本流程,但是離打造個人知名度還差很大很大一段距離.

尤其處於新手階段,需要的更是自信與外界的積極反饋,看著各平臺日益增長的閱讀量和粉絲量,心中自然不甚欣喜.

但是,持續的技術輸出能否堅持下去很大程度上靠的是外界的積極反饋,如果寫的文章基本沒人看,或者反映並不理想,估計也很難再堅持創作了.

所以筆者每天晚上都會統計一下各個平臺的資料,看一下有哪些收穫,只有看得見的資料才能給我安全感和自信心.

下面簡單展示一下每日資料統計效果:

每日資料統計

這裡列出的平臺預設是沒有提供資料分析功能,而有些平臺已經提供資料分析,說不定還要豐富圖表分析功能,自然不用像下面這般複雜操作.

所以,針對沒有提供資料分析的平臺,只好採用人工方式進行每日資料統計,一開始文章比較少,用肉眼加計算器就能很輕鬆得到閱讀量和粉絲數等資料.

但是,隨著文章的每日更新,不斷累加的文章越來越多,人工方式簡直讓我崩潰,比如昨晚在統計慕課網手記相關資料時就意外被一旁的小侄子打斷三次!

簡直不可忍受,窮則思變,懶則想法偷懶,所以是時候探索新的方式解決純手動的弊端了!

全網彙總資料

other-static-overview-201904.png

慕課手記

other-static-imooc-201904.png

簡書

other-static-jianshu-201904.png

部落格園

other-static-cnblogs-201904.png

騰訊雲社群

other-static-tencent-cloud-201904.png

圖表渲染效果來自 gitbookchart 外掛,詳情請參考 官網文件

懶則想法偷懶

回顧操作流程

要想解放重複勞動量,必須先知道問題瓶頸,現在先回顧一下手動操作流程.

  1. 登入各大部落格平臺後臺,找到文章列表.
  2. 開啟計算器按照閱讀量等指標累加每篇文章的相關資料.
  3. 更新統計頁面資料,利用 chart 外掛渲染圖示.
  4. 修改 chart 渲染資料語法,截圖渲染效果.
  5. 確認渲染效果並推送到 github 網站

本來不必利用截圖表示圖表的,只是無奈 github 不支援 chart 外掛語法,只好用截圖代替了.

思考問題瓶頸

分析上述流程後不難發現,最複雜也是最費時費力的便是第二步的資料統計,由於要肉眼統計文章並用計算器累加,簡直是手腦並用,只有高度專注才能保證統計資料的準確性和可靠性.

這也就解釋了被打斷三次後的崩潰了,找到問題的根源了,想辦法如何解決吧!

最容易想到的解決辦法是手動複製文章列表資料,然後程式分析提取關鍵資料,最後再統計資料.

又是三步操作,再分解一下步驟,看看目前能夠解決哪部分.

  1. 手動複製文章列表資料
  2. 程式分析提取關鍵資料
  3. 統計指標資料

在這三步中,只有第二步最為關鍵,也是目前我能做到的事情,因為第一步可能需要爬蟲技術或模擬介面呼叫,總體來說,總體來說還是比較麻煩的,以後再繼續優化吧.

梳理操作流程

因此,現在先著手如何將複製後的文章列表轉化成程式能夠處理的檔案格式,進而呼叫程式統計.

下面以慕課網手記文章為例,簡單介紹下處理流程.

手動複製文章

imooc-copy.gif

現在文章已複製到檔案,應該儲存成什麼格式呢?這又是一個思考點.

imooc-without-suffix.png

由於檔案內容最終需要被程式處理,而程式處理要求資料需要具備一定的格式,因此自然不能是 txtword 這類文件,平常接觸比較多的文件資料處理一般就是 excel 或者 json 型別的文件.

這裡需要 excel 這種格式文件,但是 excel 比較笨重,還需要相關軟體才能開啟 excel 檔案,好像並不是很適合,怎麼辦呢?

但是我真的需要這種一行一行的資料格式啊,有沒有折中的處理方案?

當然有!輕量級的 csv 格式不是巧合適合簡單文件處理嗎?

csvexcel 具有類似的特徵,大體上都是一行一行一列一列地儲存資料,最適合統計資料了.

看著亂七八糟的文章列表,csv 也無法處理這種複雜資料啊,接下來還是要手動格式化資料,整理一下資料.

imooc-with-csv.png

程式分析提取

至此,我們已經完成資料分析的第一步了,接下來是如何讀取 csv 檔案,由於本人是 java 程式設計師,所以我要看一下 java 如何處理 csv 檔案.

需求很簡單,編寫一個 csv 工具類並實現基本的寫入和讀取操作即可.

說到工具類當然首選現成的開源工具了,畢竟小小的需求不值得造輪子.

尋求解決方案

說到開源工具,腦海中第一個閃現的是 Apache Commons 工具類,所以先去 maven 上搜一下有沒有 csv 相關的工具類.

線上搜尋 commons-csv

maven-search-csv.png

天不負我!果然有 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();
    }
}
複製程式碼
  • 測試寫入並讀取功能

test-write-read-csv.png

測試結果真實可用,工具類基本功能編寫完成.

test-write-read-csv-result.png

制定解決方案

已經有了 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();
}
複製程式碼

imooc-statics-result.png

很完美,終於不必再肉眼統計資料了,雖然很長程度上仍然依賴人工整理好 csv 檔案,但是目前已經解決了純手動的弊端.

因此,上述解決方案是半手動的方式,仍然還有很多可以優化的地方,等下次忍受不了這種方案時再解決!

小結

本文主要介紹了純手工統計報表遇到的諸多問題,尋求一種相對簡單的解決方案.

基本流程大致可以分為下述流程:

  1. 手動複製文章列表(包括閱讀量,評論量和點贊數),並整理成標準的 csv 格式檔案.
  2. 編寫各個平臺的 csv 工具處理類,解析並統計 csv 檔案內容.
  3. 執行工具類得到最終統計資料,大功告成!

本文主要介紹的是解決問題的思路,對於其中涉及到的相關技術點並未深入展開,關鍵原始碼已經貼上,如果還想要更詳細的完整原始碼,可以留言回覆.

相關文章