从文件/文件夹名称

时间:2015-12-24 15:34:26

标签: c# .net regex sorting filenames

我需要分析一些远程资源,并从每个特定的动漫标题中选择最佳的剧集文件。决定因素主要是视频质量和文件大小。

我目前的解决方案是将所有可用文件从源排序到基于动画标题的类别,然后在分析所有源后标记所有重复项。 但是不同的文件名和拼写错误导致了误报的数量不足

所有来源都有大量文件,其中大部分文件被分隔成适当的动漫标题(但不是全部)。我正在尝试将所有文​​件归类为list of Anime titles (我来自动漫新闻网)。对于特定文件,我将文件名拆分为基于单词的关键字,并查找与标题列表中每个条目的匹配项。如果文件夹名称也与同一类别匹配,我会在文件中为分配获得分数,并进一步提高分数。

foreach (FileInfo file in allFiles)
{
    string[] subStrings = file.Name.Split(removables, StringSplitOptions.RemoveEmptyEntries);
    // score holds a value for each title, highest score indicates closer match
    int[] score = new int[titles.Count];
    bool hasAScore = false;
    // list's length - 1 to avoid extensions from being checked
    for (int i = 0; i < titles.Count; i++)
    {
        for (int j = 0; j < subStrings.Length - 1; j++)
        {
            // @\b defines the match to be specific to whole words
            if (Regex.IsMatch(titles[i], @"\b" + subStrings[j] + @"\b", RegexOptions.IgnoreCase))
            {
                foreach (string s in file.Directory.Name.Split(removables, StringSplitOptions.RemoveEmptyEntries))
                {
                    if (Regex.IsMatch(titles[i], @"\b" + s + @"\b", RegexOptions.IgnoreCase))
                    {
                        score[i]++;
                    }
                }               
                score[i]++;
                hasAScore = true;
                // Console.WriteLine("Found match with title '{0}' with string '{1}' from file '{2}'", titles[j], subStrings[i], file.Name);
            }
        }
    }
    if (hasAScore)
    {
        // Find the highest score in the list and use it's title value as the title of the Category
        string titleName = titles[Array.IndexOf(score, score.Max())];
        bool exists = false;
        // Check through all the categories if it already exists, otherwise add a new one
        // TODO perhaps check this in the class's constructor
        foreach (Category c in categories)
        {
            if (c.Name == titleName)
            {
                c.AddChildren(file, titleName);
                exists = true;
                break;
            }
        }
        if (!exists)
        {
            categories.Add(new Category(file, titleName));
        }
    }
    else
    {
        // Files without a score were not matched with any existing category
        notSorted++;
    }
}
return categories;
}

这会导致许多误报,因为数据库中的某些标题名称较长,较小的动词会提高分数。我在文件名和匹配的标题中应用了比率检查,但这对排序没有多大帮助。

// if the percentage of word matches and total words in the title is > 80% (arbitrary value)
// boost the score
int titleWordCount = titles[i].Split(removables, StringSplitOptions.RemoveEmptyEntries).Length;
if ((100 * (score[i])/ (2 * titleWordCount)) > 80)
{
    score[i] += 2;
}

我试图只检查动漫电视节目(并避免电影,OVA发行),但结果仍不令人满意。

大多数文件都是从Torrent或编码器网站下载的,导致文件名称复杂,包括文件质量和编码器签名。

例如:

ShingekinoKyojinOVA-01(480p)[Hatsuyuki-Kaitou][D8E8CC75].mkv -- Category "Shingeki no Kyojin"
(Hi10)_Gosick_-_22_The_Christmas_Carol_Adorns_the_Happiness_by_the_Window_(BD_720p)_(Broken).mkv -- Category "Gosick"
[AnimeKens.com]_[sofcj-raws]_SnK-Oad_1_[SD-480].mkv -- Category "Shingeki no Kyojin"
Commie_Steins Gate 01 Prologue to the Beginning and End.mkv -- Category "Steins Gate"
Commie_Steins_Gate_02_BD_720p_AnimeKens.com.mkv -- Category "Steins Gate"

关于如何解决这个问题的任何想法?是否存在针对此类问题的开源库?

或者我应该实施机器学习模块来预测文件名中的标题?但是我不会有固定数量的输入变量。

请帮助,如果这是提出这个问题的正确位置。如果没有,请指出正确的方向。感谢

1 个答案:

答案 0 :(得分:4)

许多年前,我不得不提出一些代码来匹配目录数据库中不同版本的书籍。起初,不太复杂。

然后我们挖掘了实际数据。标题改变了(可能是从'一个很棒的X指南'到'一个新的奇妙的X指南')。作者来自集团创作的作品。出版商改变了。无论我们尝试了什么(缺少完整的映射列表,如果我们有的话),任何完全自动化的解决方案都会出现太多的误报和漏报,有很多不同的方式从一个版本转换到另一个版本。该....)。

所以我们把人放在循环中。给他们一个候选匹配列表,我们猜测他们正确的可能性。排序所以最好的匹配首先出现,然后是下来。起初,每个人都认为对某人来说这是一项令人讨厌的工作,但是当它开始时,事实证明它既快又简单。

这就是我在你的情况下所做的。完美的自动化解决方案接近于狙击狩猎;凶狠难以接近可靠的任何地方,并且会让你感到沮丧的是人们如何可靠地进入讨价还价。如果可能的话,运行你正在进行的那种计算,然后将候选匹配粘贴在人类面前。我的经验更快,更便宜,更好。