Take me to your leaderboard Have you ever found a good challenge to answer, answered it and then found out somebody posted a solution with a better score in the same language?

Challenge

Write a program/function that takes a PPCG question ID and outputs a leaderboard.

A leaderboard consists of the rank, the language, the score, the author and the URL of each answer. This can be output as a newline delimited string, a list of strings, a "dictionary", etc..


Rank


The rank of an answer is its position in the score hierarchy (lowest first).
Answers with shared scores must have the same rank.

Language


The name of the language is always between the last # on the first line and the first ,.
It may be a link to documentation, which must be handled by taking the user-facing text.

Score


The score of a answer is the last number on the first line.
It may be a decimal number.

Author


The author of an answer is the display name of the user that posted it.

URL


The URL of an answer will go straight to the answer.
URL shorteners are disallowed.



Specifications


Standard I/O rules apply.
Standard loopholes are forbidden.
This challenge is not about finding the shortest approach in all languages, rather, it is about finding the shortest approach in each language.
Your code will be scored in bytes, usually in the encoding UTF-8, unless specified otherwise.
Explanations, even for "practical" languages, are encouraged.


Test cases

Note that these show example output formats which need not be strictly followed. These examples were taken at the time of sandboxing, they might be outdated.

Input: 28821

1. PCRE flavor, score 40 by jimmy23013 (https://codegolf.stackexchange.com/a/31863)

Input: 92944

1. Jelly, score 12 by Dennis (https://codegolf.stackexchange.com/a/92958)
2. Befunge-98, score 38 by Hactar (https://codegolf.stackexchange.com/a/98334)
3. &gt;&lt;&gt;, score 41 by Sp3000 (https://codegolf.stackexchange.com/a/92980)
4. TovTovTov, score 810147050 by Yaniv (https://codegolf.stackexchange.com/a/93048)

Input: 47604*

1. Pyth, score 28.08 by Jakube (https://codegolf.stackexchange.com/a/47642)
2. APL, score 39.6 by jimmy23013 (https://codegolf.stackexchange.com/a/47606)

Input: 133793

1. Lua, score 9.06 by TehPers (https://codegolf.stackexchange.com/a/135775)
2. C# (.NET Core), score 10.20 by Kamil Drakari (https://codegolf.stackexchange.com/a/135764)
3. Cubically, score 86.98 by Kamil Drakari (https://codegolf.stackexchange.com/a/137695)


*Note that this challenge has 3 answers, however the GolfScript answer doesn't have a comma in the header which makes it undefined behaviour.

In a few better formats:

28821, 92944, 47604, 133793

28821 92944 47604 133793

28821
92944
47604
133793


This challenge was sandboxed.
C# (.NET Core), 1059 1049 1033 998 973 bytes

Saved 53 bytes thanks to @TheLethalCoder.
Saved 25 bytes thanks to @Mr. Xcoder.



using HtmlAgilityPack;namespace System.Linq{n=&gt;{var u="http://codegolf.stackexchange.com/";var l=new Collections.Generic.List&lt;Tuple&lt;string,float,string,string&gt;&gt;();foreach(var x in new HtmlWeb().Load(u+"questions/"+n).GetElementbyId("answers").Descendants("div").Where(p=&gt;(p.Attributes["id"]?.Value??"").Contains("answer-"))){var b=x.Descendants().First(p=&gt;(p.Attributes["class"]?.Value)=="post-text");var h=b.Descendants().ElementAt(1).InnerText;l.Add(new Tuple&lt;string,float,string,string&gt;(h.Split(',',' ')[0],float.Parse(h.Split(' ').Reverse().First(p=&gt;float.TryParse(p.Replace('.',','),out var y)).Replace('.', ',')),b.ParentNode.Descendants("td").Last(p=&gt;(p.Attributes["class"]?.Value)=="post-signature").Descendants("div").Reverse().ElementAt(1).Descendants("a").First().InnerText,u+"a/"+x.Attributes["id"].Value.Split('-')[1]));}var s=new string[l.Count];for(var i=0;i&lt;l.Count;){var m=l[i];s[i]=++i+$". {m.Item1}, score {m.Item2} by {m.Item3} ({m.Item4})";}return s;}}


Uses the HTMLAgilityPack.

There are probably better solutions to this using the StackOverflow API, but this is a raw HTML solution.



Ungolfed code: (Unchanged for readability &amp; reference)

n =&gt;
{
    // Retrieve the HTML of the question page with ID n
    var doc = new HtmlWeb().Load("https://codegolf.stackexchange.com/questions/" + n);
    // Get all the answers
    var answers = doc.GetElementbyId("answers").Descendants("div").Where(d =&gt; (d.Attributes["id"]?.Value ?? "").Contains("answer-"));

    // Format: Language, Score, Author, URL
    var l = new Collections.Generic.List&lt;Tuple&lt;string, float, string, string&gt;&gt;();

    // Loop over every answer element
    foreach (var a in answers)
    {
        // Get the content of the answer post
        var b = a.Descendants().First(d =&gt; (d.Attributes["class"]?.Value ?? "") == "post-text");
        // Get the header
        var h = b.Descendants().ElementAt(1);
        // Dummy variable for the TryParse
        float y;
        // Create a new Tuple
        var v = new Tuple&lt;string, float, string, string&gt;(
            h.InnerText.Split(',', ' ')[0], // The language
            float.Parse(h.InnerText.Split(' ').Reverse().First(x =&gt; float.TryParse(x.Replace('.',','), out y)).Replace('.', ',')), // The score of the answer
            b.ParentNode.Descendants("td").Last(d =&gt; (d.Attributes["class"]?.Value ?? "") == "post-signature").Descendants("div").Reverse().ElementAt(1).Descendants("a").First().InnerText, // The author
            "https://codegolf.stackexchange.com/a/" + a.Attributes["id"].Value.Split('-')[1] // The url to the answer
            );
        l.Add(v); // Add the tuple to the collection
    }
    var s = new string[l.Count]; // An array to save the leadboard content
    for (var i = 0; i &lt; l.Count;i++)
    {
        var m = l[i]; // The current element
        s[i] = $"{i+1}. {m.Item1}, score {m.Item2} by {m.Item3} ({m.Item4})"; // Format the data
    }
    return s;
}