winforms 如何获得下载文件链接描述太?

q9rjltbz  于 2022-11-16  发布在  其他
关注(0)|答案(3)|浏览(132)

链接示例:

<img src="https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg" alt="This is the description i want to get too" >

以及我用来解析html下载源文件中链接的方法:

public List<string> GetLinks(string message)
        {
            List<string> list = new List<string>();
            string txt = message;
            foreach (Match item in Regex.Matches(txt, @"(http|ftp|https):\/\/([\w\-_]+(?:(?:\.[\w\-_]+)+))([\w\-\.,@?^=%&amp;:/~\+#]*[\w\-\@?^=%&amp;/~\+#])?"))
            {
                if (item.Value.Contains("thumbs"))
                {
                    int index1 = item.Value.IndexOf("mp4");

                    string news = ReplaceLastOccurrence(item.Value, "thumbs", "videos");

                    if (index1 != -1)
                    {
                        string result = news.Substring(0, index1 + 3);
                        if (!list.Contains(result))
                        {
                            list.Add(result);
                        }
                    }
                }
            }

            return list;
        }

但这将只给予我想要得到的链接,在这个例子中也给出链接描述:
这是个考验
然后使用它:

string[] files = Directory.GetFiles(@"D:\Videos\");
            foreach (string file in files)
            {
                foreach(string text in GetLinks(File.ReadAllText(file)))
                {
                    if (!videosLinks.Contains(text))
                    {
                        videosLinks.Add(text);
                    }
                }
               
            }

下载链接时:

private async void btnStartDownload_Click(object sender, EventArgs e)
        {
            if (videosLinks.Count > 0)
            {
                for (int i = 0; i < videosLinks.Count; i++)
                {
                    string fileName = System.IO.Path.GetFileName(videosLinks[i]);
                    await DownloadFile(videosLinks[i], @"D:\Videos\videos\" + fileName);
                }
            }
        }

但fileName是每个链接的描述。

brc7rcf0

brc7rcf01#

您可以使用Html Agility Pack,这是一个用C#编写的HTML解析器来读/写DOM,并支持纯XPATH或XSLT。在下面的示例中,您可以在alt属性和其他属性中检索描述。

实作:

using HtmlAgilityPack;
using System;
                    
public class Program
{
    public static void Main()
    {
        HtmlDocument doc = new HtmlDocument();
        var html = "<img src=\"https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg\" alt=\"This is the description i want to get too\" >";
        doc.LoadHtml(html);
        HtmlNode image = doc.DocumentNode.SelectSingleNode("//img");

        Console.WriteLine("Source: {0}", image.Attributes["src"].Value);
        Console.WriteLine("Description: {0}", image.Attributes["alt"].Value);
        Console.Read();
    }
}

示范:

https://dotnetfiddle.net/nAAZDL

输出:

Source: https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg
Description: This is the description i want to get too
vxqlmq5t

vxqlmq5t2#

Ibrahim's answer说明了使用适当的HTML解析器可以非常简单地完成这一任务,但我认为,如果您只想从单个页面中提取单个标记,或者不想使用外部依赖项,那么正则表达式并不是不合理的,特别是如果您可以对要匹配的HTML进行某些假设的话。

**请注意,下面的模式和代码仅用于演示目的,并不意味着是一个健壮的、详尽的标记解析器;读者可以根据需要对它们进行扩充,以处理他们在各种各样的Web中可能遇到的各种HTML怪癖和特点。**例如,该模式将不匹配属性值用单引号括起来或根本不带引号的图像标记,如果标记具有多个同名属性,则代码将抛出异常。

我会用一个模式来完成这个任务,这个模式将匹配一个<img />标记和它的所有属性对...

<img(?:\s+(?<name>[a-z]+)="(?<value>[^"]*)")*\s*/?>

...然后您可以通过查询找到您关心的属性。您可以使用该模式将图像属性提取到Dictionary<string, string>中,如下所示...

static IEnumerable<Dictionary<string, string>> EnumerateImageTags(string input)
{
    const string pattern =
@"
<img                     # Start of tag
    (?:                  # Attribute name/value pair: noncapturing group
        \s+              # One or more whitespace characters
        (?<name>[a-z]+)  # Attribute name: one or more letters
        =                # Literal equals sign
        ""               # Literal double quote
        (?<value>[^""]*) # Attribute value: zero or more non-double quote characters
        ""               # Literal double quote
    )*                   # Zero or more attributes are allowed
    \s*                  # Zero or more whitespace characters
/?>                      # End of tag with optional forward slash
";

    foreach (Match match in Regex.Matches(input, pattern, RegexOptions.IgnorePatternWhitespace))
    {
        string[] attributeValues = match.Groups["value"].Captures
            .Cast<Capture>()
            .Select(capture => capture.Value)
            .ToArray();
        // Create a case-insensitive dictionary mapping from each capture of the "name" group to the same-indexed capture of the "value" group
        Dictionary<string, string> attributes = match.Groups["name"].Captures
            .Cast<Capture>()
            .Select((capture, index) => new KeyValuePair<string, string>(capture.Value, attributeValues[index]))
            .ToDictionary(pair => pair.Key, pair => pair.Value, StringComparer.OrdinalIgnoreCase);

        yield return attributes;
    }
}

给定SO74133924.html...

<html>
    <body>
        <p>This image comes from https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg:
        <img src="https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg" alt="This is the description i want to get too">
        <p>This image has additional attributes on multiple lines in a self-closing tag:
        <img
            first="abc"
            src="https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg"
            empty=""
            alt="This image has additional attributes on multiple lines in a self-closing tag"
            last="xyz"
        />
        <p>This image has empty alternate text:
        <img src="https://example.com/?message=This image has empty alternate text" alt="">
        <p>This image has no alternate text:
        <img src="https://example.com/?message=This image has no alternate text">
    </body>
</html>

...您将使用每个标记的属性字典,如下所示...

static void Main()
{
    string input = File.ReadAllText("SO74133924.html");

    foreach (Dictionary<string, string> imageAttributes in EnumerateImageTags(input))
    {
        foreach (string attributeName in new string[] { "src", "alt" })
        {
            string displayValue = imageAttributes.TryGetValue(attributeName, out string attributeValue)
                ? $"\"{attributeValue}\"" : "(null)";
            Console.WriteLine($"{attributeName}: {displayValue}");
        }
        Console.WriteLine();
    }
}

...输出此...

src: "https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg"
alt: "This is the description i want to get too"

src: "https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg"
alt: "This image has additional attributes on multiple lines in a self-closing tag"

src: "https://example.com/?message=This image has empty alternate text"
alt: ""

src: "https://example.com/?message=This image has no alternate text"
alt: (null)
nsc4cvqm

nsc4cvqm3#

如果你使用regex的代码,它会占用更多的CPU周期,执行速度很慢。使用一些像angleSharp的库。
我试着用AngleSharp写你的代码。我就是这么做的。

string test = "<img src=\"https://thumbs.com/thumbs/test.mp4/test1.mp4-3.jpg\" alt=\"This is the description i want to get too\" >\r\n";
        var configuration = Configuration.Default.WithDefaultLoader();
        var context = BrowsingContext.New(configuration);
        using var doc = await context.OpenAsync(req => req.Content(test));

        string href = doc.QuerySelector("img").Attributes["alt"].Value;

相关问题