Rosetta Code/Rank languages by popularity

You are encouraged to solve this task according to the task description, using any language you may know.
Task

Sort the most popular computer programming languages based in number of members in Rosetta Code categories.

Sample output on 01 juin 2022 at 14:13 +02

Rank:  1 (1,540 entries) Phix
Rank:  2 (1,531 entries) Wren
Rank:  3 (1,507 entries) Julia
Rank:  4 (1,494 entries) Go
Rank:  5 (1,488 entries) Raku
Rank:  6 (1,448 entries) Perl
Rank:  7 (1,402 entries) Nim
Rank:  8 (1,382 entries) Python
Rank:  9 (1,204 entries) C
Rank: 10 (1,152 entries) REXX
...


Notes
 
   Each language typically demonstrates one or two methods of accessing the data: 
   with web scraping   (via http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000)
   with the API method   (examples below for Awk, Perl, Ruby, Tcl, etc). 
   The scraping and API solutions can be separate subsections, see the Tcl example.
   Filtering wrong results is optional.   You can check against Special:MostLinkedCategories (if using web scraping)
If you use the API, and do elect to filter, you may check your results against this complete, accurate, sortable, wikitable listing of all 869 programming languages, updated periodically, typically weekly.
   A complete ranked listing of all   813   languages (from the REXX example) is included here   ──►   output from the REXX program.


/* rc_rank_languages_by_popularity.wren */
 
import "./pattern" for Pattern
import "./fmt" for Fmt
 
var CURLOPT_URL = 10002
var CURLOPT_FOLLOWLOCATION = 52
var CURLOPT_WRITEFUNCTION = 20011
var CURLOPT_WRITEDATA = 10001
 
foreign class Buffer {
    construct new() {}  // C will allocate buffer of a suitable size
 
    foreign value       // returns buffer contents as a string
}
 
foreign class Curl {
    construct easyInit() {}
 
    foreign easySetOpt(opt, param)
 
    foreign easyPerform()
 
    foreign easyCleanup()
}
 
var curl = Curl.easyInit()
 
var getContent = Fn.new { |url|
    var buffer = Buffer.new()
    curl.easySetOpt(CURLOPT_URL, url)
    curl.easySetOpt(CURLOPT_FOLLOWLOCATION, 1)
    curl.easySetOpt(CURLOPT_WRITEFUNCTION, 0)  // write function to be supplied by C
    curl.easySetOpt(CURLOPT_WRITEDATA, buffer)
    curl.easyPerform()
    return buffer.value
}
 
var unescs = [
    ["_", " "],
    ["\%2B", "+"],
    ["\%C3\%A9", "é"],
    ["\%C3\%A0", "à"],
    ["\%C5\%8D", "ō"],
    ["\%C3\%A6", "æ"],
    ["\%CE\%9C", "μ"],
    ["\%D0\%9C\%D0\%9A", "МК"],
    ["\%E0\%AE\%89\%E0\%AE\%AF\%E0\%AE\%BF\%E0\%AE\%B0\%E0\%AF\%8D", "உயிர்"]
]
 
var unescape = Fn.new { |text|
    for (u in unescs) text = text.replace(u[0], u[1])
    return text
}
 
var url1 = "https://rosettacode.org/wiki/Category:Programming_Languages"
var content1 = getContent.call(url1)
var p1 = Pattern.new("<li><a href/=\"//wiki//Category:[+1^\"]\"")
var matches1 = p1.findAll(content1)
var languages = matches1.map { |l| unescape.call(l.capsText[0]) }.toList[0..-4] // the last 3 are spurious
var p2 = Pattern.new("\">[+1^<]<//a>\u200f\u200e ([/d~,#03/d] member~s)")
var url2 = "http://rosettacode.org/mw/index.php?title=Special:Categories&limit=4000"
var content2 = getContent.call(url2)
var matches2 = p2.findAll(content2)
var results = []
for (m in matches2) {
    var language = m.capsText[0]
    if (languages.contains(language)) {
        var numEntries = Num.fromString(m.capsText[1].replace(",", ""))
        results.add([language, numEntries])
    }
}
results.sort { |a, b| a[1] > b[1] }
System.print("Languages with most entries as at 4 January, 2022:")
var rank = 0
var lastScore = 0
var lastRank = 0
for (i in 0...results.count) {
    var pair = results[i]
    var eq = " "
    rank = i + 1
    if (lastScore == pair[1]) {
        eq = "="
        rank = lastRank
    } else {
        lastScore = pair[1]
        lastRank = rank
    }
    Fmt.print("$-3d$s  $-20s  $,5d", rank, eq, pair[0], pair[1])
}