Создаю парсер URL на C#. Задача: вывести top-N доменов, top-N путей. Пути к файлам(input output) берутся из консоли, N из консоли в виде опционального флага (как его правильно реализовать?)
Работает, но хотелось бы знать, как написать лучше с вашей точки зрения. И флаг, да, его тоже!
class Program
{
static void Main(string[] args)
{
int N = 0;
if (args[0] == "-n")
if (!Int32.TryParse(args[1], out N))
throw new FormatException("N is not valid");
string input = File.ReadAllText(args[2]);
string pattern = @"(http://|https://)(?<domen>[\da-z\.-]+)/(?<path>[[\/\w \.-]*)";
Regex regex = new Regex(pattern, RegexOptions.Multiline | RegexOptions.Compiled);
MatchCollection matchCollection = regex.Matches(input);
SortedDictionary<string, int> Domens = new SortedDictionary<string, int>();
SortedDictionary<string, int> Paths = new SortedDictionary<string, int>();
for (int i = 0; i < matchCollection.Count; i++)
{
if (Domens.ContainsKey(matchCollection[i].Groups["domen"].ToString()))
(Domens[matchCollection[i].Groups["domen"].ToString()])++;
else
Domens.Add(matchCollection[i].Groups["domen"].ToString(), 1);
if (Paths.ContainsKey(matchCollection[i].Groups["path"].ToString()))
(Paths[matchCollection[i].Groups["path"].ToString()])++;
else
Paths.Add(matchCollection[i].Groups["path"].ToString(), 1);
}
//Domen и Path - 2 класса, содержащих поля: строку и частоту встречаемости, реализованы в другом файле
List<Domen> SortedDomens = new List<Domen>();
foreach (KeyValuePair<string, int> keyValue in Domens)
{
SortedDomens.Add(new logparser.Domen(keyValue.Key, keyValue.Value));
}
SortedDomens.Sort();
List<Path> SortedPaths = new List<Path>();
foreach (KeyValuePair<string, int> keyValue in Paths)
{
SortedPaths.Add(new logparser.Path(keyValue.Key, keyValue.Value));
}
SortedPaths.Sort();
//Вывод сначала общей информации, затем через статический шаблонный класс информацию о доменах и путях
//Внутри переопределен метод .ToString() в классах Domen и Path
using (System.IO.StreamWriter file = new System.IO.StreamWriter(args[3], true))
{
file.WriteLine("total URLs: {0}, domains: {1}, paths: {2}",
matchCollection.Count + SortedDomens.Count + SortedPaths.Count);
file.Close();
}
WriteToFile<Domen>.writetofile(SortedDomens, args[3], N);
WriteToFile<Path>.writetofile(SortedPaths, args[3], N);
}
}
Если взять готовый пакет для разбора аргументов (PowerArgs), то примерно так:
using PowerArgs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace ConsoleApp30
{
public class Arguments
{
[ArgShortcut("n")]
public int Top { get; set; }
[ArgPosition(0)]
[ArgRequired(PromptIfMissing = true)]
public string InputFileName { get; set; }
}
class Program
{
static void Main(string[] args)
{
var arguments = Args.Parse<Arguments>(args);
var urls = File.ReadAllLines(arguments.InputFileName)
.Select(l => new Uri(l))
.ToList();
PrintTopN(urls, "Host", u => u.Host, arguments.Top);
PrintTopN(urls, "Path", u => u.AbsolutePath, arguments.Top);
}
private static void PrintTopN(List<Uri> urls, string byText, Func<Uri, string> selector, int top)
{
Console.WriteLine("By " + byText);
var groups = urls
.GroupBy(selector)
.OrderByDescending(g => g.Count())
.Select(g => g.Key);
if (top > 0)
{
groups = groups.Take(top);
}
// File.WriteAllLines, если нужно вывести в файл
foreach (var g in groups)
{
Console.WriteLine(g);
}
}
}
}
Виртуальный выделенный сервер (VDS) становится отличным выбором
доброго времени сутоксвалилась на меня интересная задача, но не знаю с какой стороны к ней подступиться
Всем доброго времени сутокТак сложилось что в качестве СУБД использую SQL Server Compact
Делаю с помощью Selenium скриншот, обрезаю его и хочу сохранить со сжатием, но оно не происходит( - в чём загвоздка ?