在上篇文章(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