UWP 獲取博客園積分,並以圖表形式呈現變化趨勢

先看一下效果吧

 

 

1. 分析

說實話,之前還真沒在乎過博客園的排名和積分,博客園默認也不給顯示。需要自己到選項裏面勾選纔可以。

 

 之前也有幾個大佬寫過類似的文章,不過是很早了。博客園關於獲取積分的api已經變了。

也不算是api吧,畢竟不是官方公開的。不過自己可以通過查看頁面元素,找到博客園的積分url。

 

在你勾選✔了上面的選項之後,打開你的博客主頁,比如我的就是https://www.cnblogs.com/hupo376787/

按F12,調出開發者工具,進入Network選項卡。

如果在下面的列表裏面沒有數據,F5刷新一下頁面即可。

 

 

然後,點擊【sidecolumn.aspx】,右側就會出現相信的信息。

右擊【sidecolumn.aspx】,【copy link address】,這個url就是我們要找的。

然後根據這個url返回的信息,我們利用正則表達式或者其他手段找到積分和排名的數據即可。

 

2. 寫Xaml界面

既然根據上面的分析,可以拿到積分和排名的數據,那麼寫代碼就簡單多了。

我這裏使用C#來寫的,語言只是一種工具,你也可以用Java、Swift、JavaScript、Flutter等,還可以用Python寫。

無論哪一種,只要能拿到數據,用圖表展示出來即可。

在xaml中,定義一下用戶名輸入框,還有一個圖表控件。

圖表使用的Microcharts。這是一個開源的圖表控件,Github上已經斬獲1000多個✨✨✨✨✨✨✨✨✨✨

<StackPanel>
            <TextBox 
                x:Name="textBlockUser" 
                Background="Transparent"
                Padding="0, 5"
                BorderThickness="0"
                Width="200"
                HorizontalAlignment="Left"
                PlaceholderText="hupo376787"
                TextChanged="User_TextChanged"/>
            <TextBlock x:Name="textBlockDate"/>
            <TextBlock x:Name="textBlockScore"/>
            <TextBlock x:Name="textBlockRank"/>

            <charts:ChartView x:Name="microChart"
                              Height="300"/>
        </StackPanel>

 

3. 獲取網頁數據

利用HttpClient寫代碼,獲取指定url的網頁源代碼。

user是文本框可以輸入的用戶id。

然後根據Http返回來的數據,做成一個List<string>。這樣就不用寫正則表達式查找🔍了。

其實主要是我不大會寫正則表達式而已。

 不好意思暴露了。

 

 string url = "https://www.cnblogs.com/" + user + "/ajax/sidecolumn.aspx";
                HttpClient client = new HttpClient();
                HttpResponseMessage message = await client.GetAsync(url);
                string content = await message.Content.ReadAsStringAsync();
                List<string> lines = content.Replace("積分與排名", "").Split("\n").ToList();

                var scoreHeaderIndex = lines.FindIndex(x => x.Contains("積分"));
                var rankHeaderIndex = lines.FindIndex(x => x.Contains("排名"));

                int score = Convert.ToInt32(lines[scoreHeaderIndex + 1]);
                int rank = Convert.ToInt32(lines[rankHeaderIndex + 1]);

 

 

4. 生成圖表

因爲要做成趨勢圖,並且博客園返回的數據只是當天的信息,並不不包含歷史記錄。

所以需要手動記錄數據,並存放在本地。

之前那幾個大佬也是這樣子,寫成了python或者js,每天自動運行一次,保存數據。

UWP想要記錄數據,需要一點額外的權限。

因爲需要記錄txt文件,而這樣的文本文件最好放在user/document文件夾下。

首先,用記事本打開Package.appxmanifest,加上

<Capabilities>
   <uap:Capability Name="documentsLibrary" />
</Capabilities>

 

然後在vs中打開Package.appxmanifest,添加聲明。按照圖示設置。

 

這樣就有權限寫入txt到文檔文件夾了。

                StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
                StorageFile file = await storageFolder.CreateFileAsync("cnBlogs.txt", CreationCollisionOption.OpenIfExists);
                string existData = await FileIO.ReadTextAsync(file);
                List<string> list = existData.Split("\r\n").ToList();

 

我這兒首先讀取了txt裏面的數據,如果這個txt不存在,就創建。已經存在的話,直接打開讀取數據。

然後繪圖

                Random rnd = new Random();
                List<ChartEntry> entries = new List<ChartEntry>();
                foreach(var item in list)
                {
                    if (item.Trim() == "")
                        continue;

                    var singleLineArray = item.Split(",");
                    var entry = new ChartEntry((float)Convert.ToDouble(singleLineArray[1]))
                    {
                        Label = singleLineArray[0],
                        ValueLabel = singleLineArray[1],
                        Color = SKColor.Parse(String.Format("#{0:X6}", rnd.Next(0x1000000)))
                    };
                    entries.Add(entry);
                }var chart = new LineChart {
                    Entries = entries,
                    MinValue = 100000,
                    BackgroundColor = SKColors.Transparent
                };
                this.microChart.Chart = chart;

 

如果在生成折線圖的時候,不加上

BackgroundColor = SKColors.Transparent

生成的圖表默認白色。但是背景透明好看。

 

 

5. 記錄獲取的積分和排名數據

 爲了防止一天內多次打開app,重複記錄,所以我做了一個檢查。

利用System.IO寫入數據。

                string contentToWrite = "";
                //Add Today
                if (!existData.Contains(DateTime.Now.ToString("yyyy-MM-dd")))
                {
                    var entryToday = new ChartEntry((float)Convert.ToDouble(score))
                    {
                        Label = score.ToString(),
                        ValueLabel = DateTime.Now.ToString("yyyy-MM-dd"),
                        Color = SKColor.Parse(string.Format("#{0:X6}", rnd.Next(0x1000000)))
                    };
                    entries.Append(entryToday);

                    contentToWrite = existData + "\r\n" + DateTime.Now.ToString("yyyy-MM-dd") + "," + score + "," + rank;
                }
                else
                    contentToWrite = existData;

                //Write
                await FileIO.WriteTextAsync(file, contentToWrite);

 

 

6. 完成的代碼

        private async Task GetData(string user)
        {
            try
            {
                string url = "https://www.cnblogs.com/" + user + "/ajax/sidecolumn.aspx";
                HttpClient client = new HttpClient();
                HttpResponseMessage message = await client.GetAsync(url);
                string content = await message.Content.ReadAsStringAsync();
                List<string> lines = content.Replace("積分與排名", "").Split("\n").ToList();

                var scoreHeaderIndex = lines.FindIndex(x => x.Contains("積分"));
                var rankHeaderIndex = lines.FindIndex(x => x.Contains("排名"));

                int score = Convert.ToInt32(lines[scoreHeaderIndex + 1]);
                int rank = Convert.ToInt32(lines[rankHeaderIndex + 1]);

                textBlockDate.Text = DateTime.Now.ToString("yyyy-MM-dd");
                textBlockScore.Text = score.ToString();
                textBlockRank.Text = rank.ToString();

                StorageFolder storageFolder = KnownFolders.DocumentsLibrary;
                StorageFile file = await storageFolder.CreateFileAsync("cnBlogs.txt", CreationCollisionOption.OpenIfExists);
                string existData = await FileIO.ReadTextAsync(file);
                List<string> list = existData.Split("\r\n").ToList();

                Random rnd = new Random();
                List<ChartEntry> entries = new List<ChartEntry>();
                foreach(var item in list)
                {
                    if (item.Trim() == "")
                        continue;

                    var singleLineArray = item.Split(",");
                    var entry = new ChartEntry((float)Convert.ToDouble(singleLineArray[1]))
                    {
                        Label = singleLineArray[0],
                        ValueLabel = singleLineArray[1],
                        Color = SKColor.Parse(String.Format("#{0:X6}", rnd.Next(0x1000000)))
                    };
                    entries.Add(entry);
                }

                string contentToWrite = "";
                //Add Today
                if (!existData.Contains(DateTime.Now.ToString("yyyy-MM-dd")))
                {
                    var entryToday = new ChartEntry((float)Convert.ToDouble(score))
                    {
                        Label = score.ToString(),
                        ValueLabel = DateTime.Now.ToString("yyyy-MM-dd"),
                        Color = SKColor.Parse(string.Format("#{0:X6}", rnd.Next(0x1000000)))
                    };
                    entries.Append(entryToday);

                    contentToWrite = existData + "\r\n" + DateTime.Now.ToString("yyyy-MM-dd") + "," + score + "," + rank;
                }
                else
                    contentToWrite = existData;

                var chart = new LineChart {
                    Entries = entries,
                    MinValue = 100000,
                    BackgroundColor = SKColors.Transparent
                };
                this.microChart.Chart = chart;

                //Write
                await FileIO.WriteTextAsync(file, contentToWrite);
            }
            catch
            {

            }
        }

 

之所以加了try{ ... } catch{ ... },是因爲在輸入用戶名的時候,可以根據文本變化,實時檢測是不是有效的用戶,並生成圖表。

 

7. 總結

獲取並顯示數據,本身不是一件很難的事情,關鍵是怎麼利用得到的數據,並把它很友好呈現出來。

當然,我這裏也少做了一步,就是讓應用自啓動,開機的時候獲取一次數據,這樣就可以防止某天忘記打開,導致數據斷層的問題了。

關於uwp如何隨開機啓動,我還沒研究過,以後有時間的寫一些分享心得。

 

OK,Merry Christmas!Lonely Christmas!

❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️

⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄

🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄

🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅

🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎

 🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦

 
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章