在上篇文章(http://www.cnblogs.com/lightluomeng/p/7212577.html
)中,初步实现了一个可配置的网页信息分析组件。可是因为是奔着解决事情的目的去的,因此写的比较匆忙,不少细节方面的问题没有仔细考虑,因此存在很多问题。主要问题有:html
DimReduceConvertor
来将二维数组降维到一位数组,或者将更高维度的数组降维到低一个维度的数组ProcessedList
来将数据显著的标记为数组,降维操做也会基于这个判断进行ICollector
,将此接口上的Key
属性定义放在了基础的IValueConvertor
上,这样更好的保证了整个树形结构的一致性,同时能够显著的减小嵌套结构IValuePersistence
,用来解决处理后的值的持久化的问题ILogger
IOptions
模式,从而能够以全局的方式配置一些必要的信息,减小单个处理节点的配置的复杂度ITypeNameResolver
从而使得单个节点在指定名称的时候可使用简写,下降配置难度;引入了其余的ITypeResolver
从而使自动化注入和配置成为可能目前总体的类型继承关系以下(部分类型未展现):json
IOptions建设在.net core的ioc的基础之上。这个模式结合了.net core的配置系统以后,很是优雅。经过类型继承和配置类型的组合注入(在一个类型中同时注入自身的定制化配置和基类的配置),能够很方便的作到全局配置和个别配置。同时,因为IOptions<>
支持可选依赖,这样就能够给一个类型提供默认的行为,然后经过配置在必要的时候改变其行为。例如:数组
public CollectorConvertor(ILogger logger, IOptions<ConvertorOptions> options, IOptions<CollectorOptions> collectorOptions) : base(logger, options) { if (collectorOptions.Value != null) { AutoGenerateKey = collectorOptions.Value.AutoGenerateKey; AutoResolveComflict = collectorOptions.Value.AutoResolveComflict; } }
在这类型CollectorConvertor
中,同时注入了两个配置。其中ConvertorOptions
是基类的配置。咱们能够经过CollectorOptions
来覆盖基类的配置。固然,在上面的代码中,并无这么作,出于其余缘由,节点的初始化操做是经过其余方式实现的。安全
如今,把一个控制台程序的代码限定为:服务器
class Program { static void Main(string[] args) { SwitchConfiguration(); RunCore(); } public static IServiceCollection ServiceCollection { get; set; } public static IServiceProvider ServiceProvider { get; set; } public static IConfigurationRoot ConfigurationRoot { get; set; } private static void SwitchConfiguration() { var allFiles = Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory); var files = allFiles.Where(i => Regex.IsMatch(i, @".*appsettings\.?.*\.json")).ToList(); if (files.Count == 1) { Console.WriteLine("仅找到一个配置文件,加载中..."); BuildConfiguration(files[0]); } else { Console.WriteLine($"找到{files.Count}个配置文件,请选择加载第几个..."); var index = Console.ReadLine().Number<int>(); if (index == null) { Console.WriteLine("错误的输入,程序退出,回车以继续..."); Console.ReadLine(); SwitchConfiguration(); } else { var configurationName = files[index.Value]; BuildConfiguration(configurationName); } } } private static void BuildConfiguration(string fileName) { var builder = new ConfigurationBuilder() .SetBasePath(AppDomain.CurrentDomain.BaseDirectory) .AddJsonFile(fileName, true, true); var configurationRoot = builder.Build(); var collection = new ServiceCollection(); collection.AddOptions(); collection.ConfigureDefault<EnviromentBuilderOptions>(configurationRoot); var traceSource = new TraceSource("信息提取", SourceLevels.All); traceSource.Listeners.Add(new ConsoleTraceListener()); collection.AddSingleton<ILogger, TraceSourceLogger>(p => new TraceSourceLogger(traceSource)); collection.AddSingleton<EnviromentBuilder>(); collection.AddSingleton<ConvertorBuilder>(); var enBuilder = collection.BuildServiceProvider().GetService<EnviromentBuilder>(); var enviroment = enBuilder.Build(collection, configurationRoot); ServiceProvider = enviroment.ServiceProvider; ConfigurationRoot = configurationRoot; } private static void RunCore() { var builder = ServiceProvider.GetService<ConvertorBuilder>(); var convertor = builder.Build(); if (convertor == null) { Console.WriteLine("没法初始化convertor,程序退出"); } else { AsyncHelper.Synchronize(() => convertor.ProcessAsync(null)); Console.WriteLine("处理完成..."); } } }
经过配置来抓取不一样网站的信息。好比,咱们使用如下配置来抓取博客园新闻的前10页的标题:网络
"ConvertorBuildOptions": { "TypeName": "Collector", "PersistenceTypeName":"ConsoleOutputPersistence", "Children": [ { "Key": "博客园前10页全部的文章title", "TypeName": "Container", "Children": [ { "TypeName": "NumberList", "Properties": { "From": 1, "To": 10 } }, { "TypeName": "Formatter", "Properties": { "Formatter": "https://news.cnblogs.com/n/page/{0}/" } }, {"TypeName":"Url2Html"}, { "TypeName": "Xpath", "Properties": { "Xpath": "//h2[@class=\"news_entry\"]/a", "ValueProvider": "InnerText" } }, { "TypeName": "DimReduce" } ] } ] }
很显然,经过配置上的改进,这个配置文件已经缩短了不知道多少,配置起来也更加清晰明了。下面是输出的内容,这里使用了一个在控制台输出的仓储实现:app
处理节点支持并行运算,基础的ConvertorOptions
能够配置这个功能,可是有些实现会忽略这个配置。例如,就上述操做而言,开启并行和不开启并行的状况下的耗时分别是:500ms 和 949ms。若是是前100页的抓取任务的话,那么结果分别是:5374ms 和 9077ms。实验机器的配置是:ide
注意,这个性能数据可能会由于站点的安全防御措施以及网络带宽的影响变得极其不稳定。
函数
在附件中打包了文章中描述的代码的源码,同时包含一个可运行的程序和若干配置。因为代码中使用了局域网内部署的nuget服务器,因此有些包是没法还原的,这里直接把程序集附上。可下载的连接是 :性能
http://pan.baidu.com/s/1eRPtxYU