通过C#从网站获取特定内容

6
为了一个非商业私立学校项目,我正在创建一款软件,可以基于当前在Spotify播放的歌曲搜索歌词。我必须使用C#(要求),但如果我愿意,我也可以使用其他语言。
我已经找到了一些网站,可以用来获取歌词。我已经成功获取了整个HTML代码,但之后我不确定该怎么做。我问了我的老师,她告诉我使用XML(我也觉得它很复杂:p),所以我阅读了很多关于它的文章并搜索了示例,但没有找到任何似乎适用于我的情况的东西。
现在是时候写一些代码了。
假设我想从musixmatch.com获取歌词:
<span data-reactid="199">
    <p class="mxm-lyrics__content" data-reactid="200">First line of the lyrics!
        These words will never be ignored
        I don't want a battle
    </p>
    <!-- react-empty: 201 -->
    <div data-reactid="202">
        <div class="inline_video_ad_container_container" data-reactid="203">
            <div id="inline_video_ad_container" data-reactid="204">
                <div class="" style="line-height:0;" data-reactid="205">
                    <div id="div_gpt_ad_outofpage_musixmatch_desktop_lyrics" data-reactid="206">
                        <script type="text/javascript">
                            //Really nice google ad JS which I have removed;
                        </script>
                    </div>
                </div>
            </div>
        </div>
        <p class="mxm-lyrics__content" data-reactid="207">But I got a war
            More fancy lyrics
            And lines
            That I want to fetch
            And display
            Tralala
            lala
            Trouble!
        </p>
    </div>
</span>

请注意,歌词的前三行位于顶部,其余部分位于底部的<p>标签内。同时,请注意两个<p>标签具有相同的类。 完整的HTML源码可在此处找到:view-source:https://www.musixmatch.com/lyrics/Bullet-for-My-Valentine/You-Want-a-Battle-Here%E2%80%99s-a-War,该片段从第97行左右开始。
因此,在这个特定的例子中,有歌词以及我不需要的相当多的代码。到目前为止,我已经尝试使用以下C#获取HTML代码:
string source = "https://www.musixmatch.com/lyrics/Bullet-for-My-Valentine/You-Want-a-Battle-Here’s-a-War";

    // The HtmlWeb class is a utility class to get the HTML over HTTP
    HtmlWeb htmlWeb = new HtmlWeb();

    // Creates an HtmlDocument object from an URL
    HtmlAgilityPack.HtmlDocument document = htmlWeb.Load(source);

    // Targets a specific node
    HtmlNode someNode = document.GetElementbyId("mxm - lyrics__content");

    if (someNode != null)
    {
        Console.WriteLine(someNode);
    } else
    {
        Console.WriteLine("Nope");
    }

    foreach (var node in document.DocumentNode.SelectNodes("//span/div[@id='site']/p[@class='mxm-lyrics__content']"))
    {
        // here is your text: node.InnerText    "//div[@class='sideInfoPlayer']/span[@class='wrap']"
        Console.WriteLine(node.InnerText);
    }

    Console.ReadKey();

整个HTML的获取已经成功,但是提取失败了。我卡在从HTML中提取歌词上。由于这个页面的歌词不在ID标签中,所以我不能只使用GetElementbyId有人能指点我正确的方向吗?我想要支持多个网站,因此需要针对不同的网站进行多次操作。


3
也许使用他们的 API 是有意义的?每天免费使用 2K 次请求。https://developer.musixmatch.com/mmplans。(供参考) - Artiom
1
mxm-lyrics__content是元素的, 而不是ID,这就是为什么GetElementbyId找不到它。您可以使用此问题中的技术按类获取它。https://dev59.com/rmYr5IYBdhLWcg3wVYog - stuartd
你不应该阅读 HTML 部分。像 @Artiom 提到的那样,使用他们的 API。这通常会给你提供 XML 或 JSON。你可以使用常见的 C# API 或 Newtonsoft.JSON 轻松阅读它们。XML 或 JSON 的优势在于,你可以轻松将数据流转换为纯 C# 对象。 - Sebi
1
@MagicLegend 我错过了。 - Artiom
@Artiom 在免费软件上可能没有太大的区别。否则,API更改通常会向用户通知或成为新版本,并且仍将正常工作。在那里,您有更好的机会做出反应或其他。但是您是正确的,在一个自由的学校项目中,这不是问题。 - Sebi
显示剩余6条评论
1个回答

3

其中一种解决方案

var htmlWeb = new HtmlWeb();
var documentNode = htmlWeb.Load(source).DocumentNode;

var findclasses = documentNode.Descendants("p")
    .Where(d => d.Attributes["class"]?.Value.Contains("mxm-lyrics__content") == true);
//or
var findclasses = documentNode.SelectNodes("//p[contains(@class,'mxm-lyrics__content')]")
var text = string.Join(Environment.NewLine, findclasses.Select(x => x.InnerText));

谢谢!运行得非常好。你有一些文档(这种符号叫什么?)关于你用第一个“findclasses”变量执行的魔法吗?你是如何构建这样的东西的? - MagicLegend
@Sebi正则表达式被认为不是解析HTML的最佳方案。请查看此答案https://dev59.com/X3I-5IYBdhLWcg3wq6do#1732454。它很棒。 - Artiom
1
@MagicLegend 搜索 Linq ;) - Sebi
@MagicLegend 变量 var 是隐式类型。如果你声明一个字符串变量,如 string value = "",你知道(编译器也知道)它是一个字符串,无需显式地写出来。而且它强制你用更好的方式命名变量。 - Artiom
1
@MagicLegend 使用 var 是基于个人观点的。但在许多情况下,它可以使您的代码更清晰。想象一下,您实例化一个字典:Dictionary<object, List<MyHolyOwnClass>> dic = new Dictionary<object, List<MyHolyOwnClass>> 与 var dic = new Dictionary<object, List<MyHolyOwnClass>> 相比。 - Sebi
显示剩余4条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接