先看一下效果吧python
1. 分析ajax
說實話,以前還真沒在意過博客園的排名和積分,博客園默認也不給顯示。須要本身到選項裏面勾選才能夠。正則表達式
以前也有幾個大佬寫過相似的文章,不過是很早了。博客園關於獲取積分的api已經變了。api
也不算是api吧,畢竟不是官方公開的。不過本身能夠經過查看頁面元素,找到博客園的積分url。app
在你勾選✔了上面的選項以後,打開你的博客主頁,好比個人就是https://www.cnblogs.com/hupo376787/dom
按F12,調出開發者工具,進入Network選項卡。async
若是在下面的列表裏面沒有數據,F5刷新一下頁面便可。ide
而後,點擊【sidecolumn.aspx】,右側就會出現相信的信息。工具
右擊【sidecolumn.aspx】,【copy link address】,這個url就是咱們要找的。this
而後根據這個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 Christians!
❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️❄️
⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄⛄
🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄🎄
🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅🎅
🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎🍎
🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦🧦