XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet

XFENewsApplication

【WinUI】新闻软件

公开
关注 0 Fork 0 Star 0
返回提交历史

XFEstudio/XFENewsApplication

初步完善微博和bilibili的热搜

402b758
XFE工作室室长 <mail@xfegzs.com>
提交于

代码差异

7 个文件 +203 -12
Modified XFENewsApplication.Core/Models/NewsSource.cs +1 -0
@@ -9,5 +9,6 @@ public class NewsSource
9 9 public string? PublishTime { get; set; }
10 10 public string? Abstract { get; set; }
11 11 public string? ImageUrl { get; set; }
12 public int Index { get; set; }
12 13 public string Source { get; set; } = string.Empty;
13 14 }
Modified XFENewsApplication.Core/Utilities/Helpers/ClimbHelper.cs +72 -0
@@ -1,4 +1,5 @@
1 1 using System.Text.Json;
2 using System.Text.RegularExpressions;
2 3 using XFEExtension.NetCore.StringExtension;
3 4 using XFEExtension.NetCore.XFETransform.JsonConverter;
4 5 using XFENewsApplication.Core.Models;
@@ -127,4 +128,75 @@ public static class ClimbHelper
127 128 Count = totalCount
128 129 };
129 130 }
131
132 public static async Task<NewsResult> ClimbWeiboHotSearch(CancellationToken cancellationToken)
133 {
134 int index = 0;
135 string message = "Success";
136 var resultList = new List<NewsSource>();
137 try
138 {
139 using var client = new HttpClient();
140 client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");
141 QueryableJsonNode jsonNode = await client.GetStringAsync("https://m.weibo.cn/api/container/getIndex?containerid=106003type%3D25%26t%3D3%26disable_hot%3D1%26filter_type%3Drealtimehot&luicode=20000061&lfid=5070140584495876", cancellationToken);
142 foreach (var node in jsonNode["data"]["cards"].GetChildNodes().First()["card_group"]["package:list", "desc", "desc_extr", "icon"].PackageInListObject())
143 {
144 if (node.TryGetValue("desc_extr", out var desc_extr) && !desc_extr.ToString().IsNullOrWhiteSpace())
145 resultList.Add(new NewsSource
146 {
147 Title = Regex.Unescape(node["desc"].ToString()),
148 Abstract = Regex.Unescape(desc_extr.ToString()),
149 Source = "微博热搜",
150 Index = index++,
151 ImageUrl = node.TryGetValue("icon", out var icon) ? icon.ToString() : string.Empty
152 });
153 }
154 }
155 catch (Exception ex)
156 {
157 message = ex.Message;
158 }
159 return new()
160 {
161 NewsSourceList = resultList,
162 Success = resultList.Count > 0,
163 Message = message,
164 Count = resultList.Count
165 };
166 }
167
168 public static async Task<NewsResult> ClimbBilibiliHotSearch(CancellationToken cancellationToken)
169 {
170 int index = 0;
171 string message = "Success";
172 var resultList = new List<NewsSource>();
173 try
174 {
175 using var client = new HttpClient();
176 client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");
177 QueryableJsonNode jsonNode = await client.GetStringAsync("https://api.bilibili.com/x/web-interface/wbi/search/square?limit=50&platform=web&web_location=333.1007&w_rid=2247c88d4bf6d1fbd138018aa2c530d5&wts=1744698017", cancellationToken);
178 foreach (var node in jsonNode["data"]["trending"]["list"]["package:list", "keyword", "heat_score", "icon"].PackageInListObject())
179 {
180 resultList.Add(new NewsSource
181 {
182 Title = node["keyword"].ToString(),
183 Abstract = node["heat_score"].ToString(),
184 Source = "B站热搜",
185 Index = index++,
186 ImageUrl = node.TryGetValue("icon", out var icon) ? icon.ToString() : string.Empty
187 });
188 }
189 }
190 catch (Exception ex)
191 {
192 message = ex.Message;
193 }
194 return new()
195 {
196 NewsSourceList = resultList,
197 Success = resultList.Count > 0,
198 Message = message,
199 Count = resultList.Count
200 };
201 }
130 202 }
Modified XFENewsApplication.Test/Program.cs +19 -9
@@ -1,21 +1,31 @@
1 using XFEExtension.NetCore.XFETransform.JsonConverter;
1 using System.Text.RegularExpressions;
2 using XFEExtension.NetCore.StringExtension;
3 using XFEExtension.NetCore.XFETransform.JsonConverter;
2 4
3 5 class Program
4 6 {
5 7 //[SMTest]
6 public static string TestMethod()
8 public static async Task TestWeiboHotSearch()
7 9 {
8 return Path.GetExtension("adwada.png");
10 using var client = new HttpClient();
11 client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");
12 QueryableJsonNode jsonNode = await client.GetStringAsync("https://m.weibo.cn/api/container/getIndex?containerid=106003type%3D25%26t%3D3%26disable_hot%3D1%26filter_type%3Drealtimehot&luicode=20000061&lfid=5070140584495876");
13 foreach (var node in jsonNode["data"]["cards"].GetChildNodes().First()["card_group"]["package:list", "desc", "desc_extr", "icon"].PackageInListObject())
14 {
15 if (node.TryGetValue("desc_extr", out var desc_extr) && !desc_extr.ToString().IsNullOrWhiteSpace())
16 Console.WriteLine($"{Regex.Unescape(node["desc"].ToString())}\t {Regex.Unescape(desc_extr.ToString())}");
17 }
9 18 }
10 19
11 [SMTest("attitude")]
12 public static async Task<List<string>> TestBaiduTranslate(string word)
20 [SMTest]
21 public static async Task TestBilibiliHotSearch()
13 22 {
14 23 using var client = new HttpClient();
15 24 client.DefaultRequestHeaders.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/135.0.0.0 Safari/537.36 Edg/135.0.0.0");
16 var result = await client.PostAsync("https://fanyi.baidu.com/sug", new StringContent($"kw={word}"));
17 result.EnsureSuccessStatusCode();
18 QueryableJsonNode jsonNode = await result.Content.ReadAsStringAsync();
19 return [.. jsonNode["data"]["package:list", "k", "v"].PackageInListObject().Select(wordInfo => wordInfo["v"].ToString())];
25 QueryableJsonNode jsonNode = await client.GetStringAsync("https://api.bilibili.com/x/web-interface/wbi/search/square?limit=50&platform=web&web_location=333.1007&w_rid=2247c88d4bf6d1fbd138018aa2c530d5&wts=1744698017");
26 foreach (var node in jsonNode["data"]["trending"]["list"]["package:list", "keyword", "heat_score", "icon"].PackageInListObject())
27 {
28 Console.WriteLine($"{node["keyword"]}\t {node["heat_score"]}");
29 }
20 30 }
21 31 }
Modified XFENewsApplication/ViewModels/HotSearchViewPageViewModel.cs +39 -1
@@ -1,6 +1,44 @@
1 namespace XFENewsApplication.ViewModels;
1 using System.Collections.ObjectModel;
2 using XFEExtension.NetCore.WinUIHelper.Interface.Services;
3 using XFEExtension.NetCore.WinUIHelper.Utilities;
4 using XFENewsApplication.Core.Models;
5 using XFENewsApplication.Core.Utilities.Helpers;
6
7 namespace XFENewsApplication.ViewModels;
2 8
3 9 public partial class HotSearchViewPageViewModel : ViewModelBase
4 10 {
11 private List<NewsSource> hotSearchSource = [];
12 public ObservableCollection<NewsSource> HotSearchSource { get; } = [];
13 public CancellationTokenSource? TokenSource { get; set; }
14 public INavigationParameterService<string> NavigationParameterService { get; set; } = ServiceManager.GetService<INavigationParameterService<string>>();
15 public IMessageService? MessageService { get; set; } = ServiceManager.GetGlobalService<IMessageService>();
16 public INavigationViewService? NavigationViewService { get; set; } = ServiceManager.GetGlobalService<INavigationViewService>();
17
18 public HotSearchViewPageViewModel() => NavigationParameterService.ParameterChange += NavigationParameterService_ParameterChange;
19
20 private async void NavigationParameterService_ParameterChange(object? sender, string? e)
21 {
22 var tokenSource = new CancellationTokenSource();
23 TokenSource = tokenSource;
24 var result = await GetSource(e, TokenSource.Token);
25 if (result.Success)
26 LoadHotSearch(result.NewsSourceList);
27 else
28 MessageService?.ShowMessage(result.Message ?? "请检查网络连接", "无法获取", InfoBarSeverity.Warning);
29 }
30
31 private static async Task<NewsResult> GetSource(string? source, CancellationToken cancellationToken) => source switch
32 {
33 "Weibo" => await ClimbHelper.ClimbWeiboHotSearch(cancellationToken),
34 "Bilibili" => await ClimbHelper.ClimbBilibiliHotSearch(cancellationToken),
35 _ => new()
36 };
5 37
38 public void LoadHotSearch(IEnumerable<NewsSource> newsSources)
39 {
40 HotSearchSource.Clear();
41 foreach (var source in newsSources)
42 HotSearchSource.Add(source);
43 }
6 44 }
Modified XFENewsApplication/Views/AppShellPage.xaml +10 -0
@@ -41,6 +41,16 @@
41 41 <ImageIcon Source="https://www.msn.com/favicon.ico" Width="16" Height="16"/>
42 42 </NavigationViewItem.Icon>
43 43 </NavigationViewItem>
44 <NavigationViewItem Content="微博热搜" add:NavigationAddition.NavigateTo="XFENewsApplication.Views.HotSearchViewPage" add:NavigationAddition.NavigateParameter="Weibo">
45 <NavigationViewItem.Icon>
46 <ImageIcon Source="https://m.weibo.cn/favicon.ico" Width="16" Height="16"/>
47 </NavigationViewItem.Icon>
48 </NavigationViewItem>
49 <NavigationViewItem Content="BiliBili热搜" add:NavigationAddition.NavigateTo="XFENewsApplication.Views.HotSearchViewPage" add:NavigationAddition.NavigateParameter="Bilibili">
50 <NavigationViewItem.Icon>
51 <ImageIcon Source="https://www.bilibili.com/favicon.ico" Width="16" Height="16"/>
52 </NavigationViewItem.Icon>
53 </NavigationViewItem>
44 54 </NavigationView.MenuItems>
45 55 <NavigationView.FooterMenuItems>
46 56 <NavigationViewItem Content="收藏" add:NavigationAddition.NavigateTo="XFENewsApplication.Views.NewsViewPage" add:NavigationAddition.NavigateParameter="Favorite">
Modified XFENewsApplication/Views/HotSearchViewPage.xaml +36 -1
@@ -4,11 +4,46 @@
4 4 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
5 5 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
6 6 xmlns:local="using:XFENewsApplication.Views"
7 xmlns:coremodel="using:XFENewsApplication.Core.Models"
8 xmlns:converter="using:XFEExtension.NetCore.WinUIHelper.Utilities.Converter"
7 9 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
8 10 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
9 11 mc:Ignorable="d">
12 <Page.Resources>
13 <converter:URLImageConverter x:Key="URLImageConverter"/>
14 </Page.Resources>
10 15
11 16 <Grid>
12
17 <ListView ItemsSource="{x:Bind ViewModel.HotSearchSource}" IsDoubleTapEnabled="True" DoubleTapped="ListView_DoubleTapped">
18 <ListView.Header>
19 <Grid>
20 <Grid.ColumnDefinitions>
21 <ColumnDefinition Width="50"/>
22 <ColumnDefinition Width="*"/>
23 <ColumnDefinition Width="120"/>
24 <ColumnDefinition Width="50"/>
25 </Grid.ColumnDefinitions>
26 <TextBlock Text="排名"/>
27 <TextBlock Grid.Column="1" Text="内容"/>
28 <TextBlock Grid.Column="2" Text="热度"/>
29 </Grid>
30 </ListView.Header>
31 <ListView.ItemTemplate>
32 <DataTemplate x:DataType="coremodel:NewsSource">
33 <Grid>
34 <Grid.ColumnDefinitions>
35 <ColumnDefinition Width="50"/>
36 <ColumnDefinition Width="*"/>
37 <ColumnDefinition Width="120"/>
38 <ColumnDefinition Width="50"/>
39 </Grid.ColumnDefinitions>
40 <TextBlock Text="{x:Bind Index}"/>
41 <TextBlock Grid.Column="1" Text="{x:Bind Title}"/>
42 <TextBlock Grid.Column="2" Text="{x:Bind Abstract}"/>
43 <Image Grid.Column="3" Source="{x:Bind ImageUrl, Converter={StaticResource URLImageConverter}}"/>
44 </Grid>
45 </DataTemplate>
46 </ListView.ItemTemplate>
47 </ListView>
13 48 </Grid>
14 49 </Page>
Modified XFENewsApplication/Views/HotSearchViewPage.xaml.cs +26 -1
@@ -1,12 +1,37 @@
1 namespace XFENewsApplication.Views;
1 using Microsoft.UI.Xaml.Input;
2 using Microsoft.UI.Xaml.Navigation;
3
4 namespace XFENewsApplication.Views;
2 5
3 6 /// <summary>
4 7 /// 热搜页面
5 8 /// </summary>
6 9 public sealed partial class HotSearchViewPage : Page
7 10 {
11 public string? Parameter { get; set; }
12 public static HotSearchViewPage? Current { get; set; }
13 public HotSearchViewPageViewModel ViewModel { get; set; } = new();
8 14 public HotSearchViewPage()
9 15 {
16 Current = this;
10 17 this.InitializeComponent();
18 ViewModel.NavigationParameterService.Initialize(this);
19 }
20
21 protected override void OnNavigatedTo(NavigationEventArgs e)
22 {
23 base.OnNavigatedTo(e);
24 ViewModel.NavigationParameterService.OnParameterChange(e.Parameter);
25 }
26
27 protected override void OnNavigatedFrom(NavigationEventArgs e)
28 {
29 base.OnNavigatedFrom(e);
30 ViewModel.TokenSource?.Cancel();
31 }
32
33 private void ListView_DoubleTapped(object sender, DoubleTappedRoutedEventArgs e)
34 {
35
11 36 }
12 37 }