前言:并不是别人要求高,而是自己要求低。
目标:
提示:WPF
爬C初试
- 一节课 掌握
WPF
爬C初试
入门知识
学习内容:获取某.aspx类目及控制仪表盘的指向
例如:
- 搭建 WPF开发环境 安装VS 已安装没装WPF的 修改VS Installer
- 选择桌面应用程序 WPF
- 插曲 VS需要完全关闭
- 相关依赖包 还原包
- 文件目录长度的坑 爬 了很久 丢
- 掌握 WPF 爬C基本语法 获取的页面
- 开始 分割线
- 创建WPF应用程序
- 安装包文件
- 引用组件 同步命名空间 编译
Instrument.xaml
<UserControl x:Class="DataCollector.Visualization.Instrument" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" mc:Ignorable="d" FontFamily="Microsoft YaHei" d:DesignHeight="400" d:DesignWidth="400"> <Grid> <Border Name="border" Background="#FF030A28"> <Border.Effect> <DropShadowEffect BlurRadius="20" Opacity="0.5" ShadowDepth="0" Direction="0" Color="#FF3CAFFF"/> </Border.Effect> <Grid> <Path Stroke="#333CAFFF" StrokeThickness="10" Name="circle" RenderTransformOrigin="0.5,0.5"> <Path.RenderTransform> <RotateTransform Angle="-45"/> </Path.RenderTransform> </Path> <Canvas x:Name="canvasPlate" RenderTransformOrigin="0.5,0.5" Margin="0"> <Canvas.RenderTransform> <RotateTransform Angle="-45"/> </Canvas.RenderTransform> </Canvas> <Path Data="" Name="plateBorder" Stroke="#FF3CAFFF" StrokeThickness="3" RenderTransformOrigin="0.5,0.5" Width="{Binding ElementName=border,Path=Width}" Height="{Binding ElementName=border,Path=Height}"> <Path.RenderTransform> <RotateTransform Angle="-45"/> </Path.RenderTransform> </Path> <Path Data="M200 205,360 200,200 195,195 200 200 205" Fill="Red" RenderTransformOrigin="0.5,0.5" Name="pointer"> <Path.RenderTransform> <RotateTransform Angle="135" x:Name="rtPointer"/> </Path.RenderTransform> </Path> <Border Width="60" Height="60" CornerRadius="30" Background="#FF030A28"> <Border.Effect> <DropShadowEffect BlurRadius="20" Opacity="0.3" ShadowDepth="0" Direction="0" Color="#FF3CAFFF"/> </Border.Effect> <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> <TextBlock Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Center"> <Run Text="{Binding Value,RelativeSource={RelativeSource AncestorType=UserControl}}" FontSize="20"/> <Run Text="条/s" FontSize="7"/> </TextBlock> <TextBlock Text="爬C" Foreground="#FF8CBEF0" VerticalAlignment="Center" HorizontalAlignment="Center" FontSize="6"/> </StackPanel> </Border> </Grid> </Border> </Grid> </UserControl>
- Instrument.xaml.cs
using System; using System.Collections.Generic; using System.ComponentModel; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace DataCollector.Visualization { /// <summary> /// MeterPlate.xaml 的交互逻辑 /// </summary> public partial class Instrument : UserControl { // 当前值 public double Value { get { return (double)GetValue(ValueProperty); } set { SetValue(ValueProperty, value); } } public static readonly DependencyProperty ValueProperty = DependencyProperty.Register("Value", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged))); // 最小刻度 public double Minimum { get { return (double)GetValue(MinimumProperty); } set { SetValue(MinimumProperty, value); } } public static readonly DependencyProperty MinimumProperty = DependencyProperty.Register("Minimum", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged))); // 最大刻度 public double Maximum { get { return (double)GetValue(MaximumProperty); } set { SetValue(MaximumProperty, value); } } public static readonly DependencyProperty MaximumProperty = DependencyProperty.Register("Maximum", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged))); // 间隔 public double Interval { get { return (double)GetValue(IntervalProperty); } set { SetValue(IntervalProperty, value); } } public static readonly DependencyProperty IntervalProperty = DependencyProperty.Register("Interval", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged))); // 大刻度的个数 public int ScaleCount { get { return (int)GetValue(ScaleCountProperty); } set { SetValue(ScaleCountProperty, value); } } public static readonly DependencyProperty ScaleCountProperty = DependencyProperty.Register("ScaleCount", typeof(int), typeof(Instrument), new PropertyMetadata(default(int), new PropertyChangedCallback(OnPropertyChanged))); // 刻度的厚度 public double ScaleThickness { get { return (double)GetValue(ScaleThicknessProperty); } set { SetValue(ScaleThicknessProperty, value); } } public static readonly DependencyProperty ScaleThicknessProperty = DependencyProperty.Register("ScaleThickness", typeof(double), typeof(Instrument), new PropertyMetadata(default(double), new PropertyChangedCallback(OnPropertyChanged))); // 刻度的颜色 public Brush ScaleBrush { get { return (Brush)GetValue(ScaleBrushProperty); } set { SetValue(ScaleBrushProperty, value); } } public static readonly DependencyProperty ScaleBrushProperty = DependencyProperty.Register("ScaleBrush", typeof(Brush), typeof(Instrument), new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged))); // 指针的颜色 public Brush PointerBrush { get { return (Brush)GetValue(PointerBrushProperty); } set { SetValue(PointerBrushProperty, value); } } public static readonly DependencyProperty PointerBrushProperty = DependencyProperty.Register("PointerBrush", typeof(Brush), typeof(Instrument), new PropertyMetadata(default(Brush), new PropertyChangedCallback(OnPropertyChanged))); // 刻度字体大小 public new double FontSize { get { return (double)GetValue(FontSizeProperty); } set { SetValue(FontSizeProperty, value); } } public static new readonly DependencyProperty FontSizeProperty = DependencyProperty.Register("FontSize", typeof(double), typeof(Instrument), new PropertyMetadata(9.0, new PropertyChangedCallback(OnPropertyChanged))); public Instrument() { InitializeComponent(); SetCurrentValue(MinimumProperty, 0d); SetCurrentValue(MaximumProperty, 100d); SetCurrentValue(IntervalProperty, 10d); SizeChanged += (se, ev) => { Refresh(); }; } static void OnPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) => (d as Instrument).Refresh(); private void Refresh() { // 圆 this.border.Width = Math.Min(RenderSize.Width, RenderSize.Height); this.border.Height = Math.Min(RenderSize.Width, RenderSize.Height); this.border.CornerRadius = new CornerRadius(this.border.Width / 2); // 半径 double radius = this.border.Width / 2; this.canvasPlate.Children.Clear(); if (ScaleCount <= 0 || radius <= 0) return; // 画边 string borderPathData = $"M4,{radius}A{radius - 4} {radius - 4} 0 1 1 {radius} {this.border.Height - 4}"; // 将字符串转换成Geometry var converter = TypeDescriptor.GetConverter(typeof(Geometry)); this.plateBorder.Data = (Geometry)converter.ConvertFrom(borderPathData); // 计算刻度 double label = this.Minimum; double interval = 0; double step = 270.0 / (this.Maximum - this.Minimum); // 计算小刻度 for (int i = 0; i < this.Maximum - this.Minimum; i++) { //添加刻度线 Line lineScale = new Line(); // 角度需要转换弧度 lineScale.X1 = radius - (radius - 13) * Math.Cos(step * i * Math.PI / 180); lineScale.Y1 = radius - (radius - 13) * Math.Sin(step * i * Math.PI / 180); lineScale.X2 = radius - (radius - 8) * Math.Cos(step * i * Math.PI / 180); lineScale.Y2 = radius - (radius - 8) * Math.Sin(step * i * Math.PI / 180); lineScale.Stroke = this.ScaleBrush; lineScale.StrokeThickness = this.ScaleThickness; this.canvasPlate.Children.Add(lineScale); } // 计算大刻度 do { //添加刻度线 Line lineScale = new Line(); lineScale.X1 = radius - (radius - 20) * Math.Cos(interval * step * Math.PI / 180); lineScale.Y1 = radius - (radius - 20) * Math.Sin(interval * step * Math.PI / 180); lineScale.X2 = radius - (radius - 8) * Math.Cos(interval * step * Math.PI / 180); lineScale.Y2 = radius - (radius - 8) * Math.Sin(interval * step * Math.PI / 180); lineScale.Stroke = this.ScaleBrush; lineScale.StrokeThickness = this.ScaleThickness; this.canvasPlate.Children.Add(lineScale); TextBlock txtScale = new TextBlock(); txtScale.Text = label.ToString("0"); txtScale.Width = 34; txtScale.TextAlignment = TextAlignment.Center; txtScale.Foreground = new SolidColorBrush(Colors.White); txtScale.RenderTransform = new RotateTransform() { Angle = 45, CenterX = 17, CenterY = 8 }; txtScale.FontSize = this.FontSize; Canvas.SetLeft(txtScale, radius - (radius - 34) * Math.Cos(interval * step * Math.PI / 180) - 17); Canvas.SetTop(txtScale, radius - (radius - 34) * Math.Sin(interval * step * Math.PI / 180) - 8); this.canvasPlate.Children.Add(txtScale); interval += (this.Maximum - this.Minimum) / this.ScaleCount; label += (this.Maximum - this.Minimum) / this.ScaleCount; } while (interval <= this.Maximum - this.Minimum); // 修改指针 string sData = "M{0} {1},{2} {0},{0} {3},{3} {0},{0} {1}"; sData = string.Format(sData, radius, radius + 2, this.border.Width - radius / 10, radius - 4); converter = TypeDescriptor.GetConverter(typeof(Geometry)); this.pointer.Data = (Geometry)converter.ConvertFrom(sData); this.pointer.Fill = this.PointerBrush; //DoubleAnimation da = new DoubleAnimation((Value - Minimum) * step + 135, new Duration(TimeSpan.FromMilliseconds(200))); //this.rtPointer.BeginAnimation(RotateTransform.AngleProperty, da); this.rtPointer.Angle = (Value - Minimum) * step + 135; // 修改圆 M100 200 A100 100 0 1 1 200 300 // 厚度 double thickness = radius / 2; this.circle.StrokeThickness = thickness; double startX = radius - thickness / 2; double startY = radius; double endX = radius - (radius - thickness / 2) * Math.Cos((Value - Minimum) * step * Math.PI / 180); double endY = radius - (radius - thickness / 2) * Math.Sin((Value - Minimum) * step * Math.PI / 180); int isLarge = 1; if ((Value - Minimum) * step < 180) isLarge = 0; sData = $"M{startX},{startY}A{radius / 2} {radius / 2} 0 1 1 {endX} {endY}"; sData = $"M{thickness / 2},{radius}A{radius - thickness / 2} {radius - thickness / 2} 0 {isLarge} 1 {endX} {endY}"; //sData = string.Format(sData, radius * 0.5, radius, radius * 1.5); this.circle.Data = (Geometry)converter.ConvertFrom(sData); this.circle.Visibility = Visibility.Visible; if (this.border.Width < 200) this.circle.Visibility = Visibility.Collapsed; } } }
代码CategoryCrawler
// 跑起来 Fstyle
private int _Count = 1;
public List<JD_Category> Get_CategoryList(string url)
{
//下载 Html
string htmlString = WebRequestHelper.DownloadUrl(url);
List<Category> Categories = RootCategory(htmlString);
return jD_Categories;
}
/// <summary>
/// 找出 一级目录
/// </summary>
/// <param name="htmlString"></param>
private List<Category> RootCategory(string htmlString)
{
List<Category> categorylist = new List<Category>();
//解析 数据
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(htmlString);
string categoryPath = "//*[@class='category-items clearfix']/div[@class='col']/div[@class='category-item m']";
HtmlNodeCollection categoryNodeList = doc.DocumentNode.SelectNodes(categoryPath);
if (categoryNodeList != null && categoryNodeList.Count > 0)
{
foreach (var item in categoryNodeList)
{
HtmlDocument categorydoc = new HtmlDocument();
categorydoc.LoadHtml(item.OuterHtml);
string titlePath = "//*/div[@class='mt']/h2/span";
HtmlNode titleNode = categorydoc.DocumentNode.SelectSingleNode(titlePath);
int k = 1;
string code = k++.ToString("00") + "f";
if (titleNode != null)
{
categorylist.Add(new Category()
{
Id = _Count++,
State = 0,
CategoryLevel = 1,
Code = code,
ParentCode = "root",
Name = titleNode.InnerText,
});
}
categorylist.AddRange(SecondCategory(item.OuterHtml, code));
}
}
return categorylist;
}
/// <summary>
/// 这里找 二级目录
/// </summary>
/// <param name="html"></param>
/// <param name="parentCode"></param>
/// <returns></returns>
private List<Category> SecondCategory(string html, string parentCode)
{
List<Category> categoryList = new List<Category>();
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string xpath = "//*[@class='items']/dl[@class='clearfix']";
HtmlNodeCollection nodeList = doc.DocumentNode.SelectNodes(xpath);
int k = 1;
foreach (HtmlNode node in nodeList)
{
string code = $"{parentCode}{k.ToString("00")}s";
string secondHtml = node.InnerHtml;
if (string.IsNullOrWhiteSpace(secondHtml))
continue;
Category category = new Category()
{
Id = _Count++,
State = 0,
CategoryLevel = 2,
Code = code,
ParentCode = parentCode
};
HtmlDocument secondDoc = new HtmlDocument();
secondDoc.LoadHtml(secondHtml);
HtmlNode secondNode = secondDoc.DocumentNode.SelectSingleNode("//dt/a");
if (secondNode == null)//
{
secondNode = secondDoc.DocumentNode.SelectSingleNode("//dt");
}
category.Name = secondNode.InnerText;
if (secondNode.Attributes["href"] != null)
{
category.Url = secondNode.Attributes["href"].Value;
if (!category.Url.StartsWith("http:"))
{
category.Url = string.Concat("http:", category.Url);
}
}
categoryList.Add(category);
HtmlNode thirdNode = secondDoc.DocumentNode.SelectSingleNode("//dd");
if (thirdNode == null)
continue;
categoryList.AddRange(this.ThirdCategory(thirdNode.InnerHtml, code));
k++;
}
return categoryList;
}
/// <summary>
/// 获取 三级类目
/// </summary>
/// <param name="html"></param>
/// <param name="parentCode"></param>
/// <returns></returns>
private List<Category> ThirdCategory(string html, string parentCode)
{
List<Category> categoryList = new List<Category>();
HtmlDocument doc = new HtmlDocument();
doc.LoadHtml(html);
string path = "//a";
HtmlNodeCollection nodeList = doc.DocumentNode.SelectNodes(path);
if (nodeList == null || nodeList.Count == 0)
return categoryList;
int k = 1;
foreach (HtmlNode node in nodeList)
{
string code = $"{parentCode}{k.ToString("00")}t";
Category category = new Category()
{
Id = _Count++,
State = 0,
CategoryLevel = 3,
Code = code,
ParentCode = parentCode
};
category.Name = node.InnerText;
category.Url = node.Attributes["href"].Value;
if (!category.Url.StartsWith("http:"))
{
category.Url = string.Concat("http:", category.Url);
}
categoryList.Add(category);
k++;
}
return categoryList;
}
产出:
提示: