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.


-- demo\rosetta\Rank_Languages.exw
constant output_users = false,
         limit = 20,    -- 0 to list all
         languages = "http://rosettacode.org/wiki/Category:Programming_Languages",
         categories = "http://www.rosettacode.org/mw/index.php?title=Special:Categories&limit=5000"

include rosettacode_cache.e -- see Rosetta_Code/Count_examples#Phix

function correct_name(string ri)
    ri = substitute(ri,`"`,`"`)
    ri = substitute(ri,`'`,`'`)
    ri = substitute(ri,"\xE2\x80\x99","'")
    ri = substitute(ri,"\xC3\xB6","o")
    ri = substitute(ri,"%3A",":")
    ri = substitute(ri,"%E2%80%93","-")
    ri = substitute(ri,"%E2%80%99","'")
    ri = substitute(ri,"%27","'")
    ri = substitute(ri,"%2B","+")
    ri = substitute(ri,"%C3%A8","e")
    ri = substitute(ri,"%C3%A9","e")
    ri = substitute(ri,"%C3%B6","o")
    ri = substitute(ri,"%C5%91","o")
    ri = substitute(ri,"%22",`"`)
    ri = substitute(ri,"%2A","*")
    ri = substitute(ri,"\xC2\xB5","u")
    ri = substitute(ri,"\xC3\xA0","a")
    ri = substitute(ri,"\xC3\xA6","a")
    ri = substitute(ri,"\xC3\xA9","e")
    ri = substitute(ri,"\xC3\xB4","o")
    ri = substitute(ri,"\xC5\x8D","o")
    ri = substitute(ri,"\xCE\x9C","u")
    ri = substitute(ri,"\xD0\x9C\xD0\x9A","MK")
    ri = substitute(ri,"\xE0\xAE\x89\xE0\xAE\xAF\xE0\xAE\xBF\xE0\xAE\xB0\xE0\xAF\x8D/","")
    ri = substitute(ri,"APEX","Apex")
    ri = substitute(ri,"uC++ ","UC++")
    ri = substitute(ri,`CASIO BASIC`,`Casio BASIC`)
    ri = substitute(ri,`Visual BASIC`,`Visual Basic`)
    ri = substitute(ri,`INTERCAL`,`Intercal`)
    ri = substitute(ri,`SETL4`,`Setl4`)
    ri = substitute(ri,`QBASIC`,`QBasic`)
    ri = substitute(ri,`RED`,`Red`)
    ri = substitute(ri,`OCTAVE`,`Octave`)
    ri = substitute(ri,`OoREXX`,`OoRexx`)
    return ri
end function

include builtins/sets.e

constant cat_title = `title="Category:`

function extract_names()
    sequence results = {} -- {rank,count,name}

    if get_file_type("rc_cache")!=FILETYPE_DIRECTORY then
        if not create_directory("rc_cache") then
            crash("cannot create rc_cache directory")
        end if
    end if
    -- 1) extract languages from eg title="Category:Phix"
    sequence language_names = {}
    string langs = open_download("languages.htm",languages),
           language_name
    langs = langs[1..match(`<div class="printfooter">`,langs)-1]
    integer start = match("<h2>Subcategories</h2>",langs), k
    while true do
        k = match(cat_title,langs,start)
        if k=0 then exit end if
        k += length(cat_title)
        start = find('"',langs,k)
        language_name = correct_name(langs[k..start-1])
        language_names = append(language_names,language_name)
    end while

    -- 2) extract results from eg title="Category:Phix">Phix</a>?? (997 members)</li>
    --     but obviously only when we have found that language in the phase above.
    --     (note there is / ignore some wierd uncode-like stuff after the </a>...)
    string cats = open_download("categories.htm",categories)
    start = 1
    while true do
        k = match(cat_title,cats,start)
        if k=0 then exit end if
        k += length(cat_title)
        start = find('"',cats,k)
        language_name = correct_name(cats[k..start-1])
        start = match("</a>",cats,start)+4
        if output_users then
            if length(language_name)>5 
            and language_name[-5..-1] = " User" then
                language_name = correct_name(language_name[1..-6])
            else
                language_name = ""
            end if
        end if
        if length(language_name)
        and find(language_name,language_names) then
            while not find(cats[start],"(<") do start += 1 end while -- (ignore)
            string members = cats[start..find('<',cats,start+1)]
            members = substitute(members,",","")
            sequence res = scanf(members,"(%d member%s)<")
            results = append(results,{0,res[1][1],language_name})
        end if      
    end while
    results = sort_columns(results,{-2,3}) -- (descending 2nd column, then asc 3rd)

    --3) assign rank
    integer count, prev = 0, rank
    for i=1 to length(results) do
        count = results[i][2]
        if count=prev then
            results[i][1] = "="
        else
            rank = i
            results[i][1] = sprint(rank)
            prev = count
        end if
    end for

    return results
end function

procedure show(sequence results)
    progress("")
    for i=1 to iff(limit?limit:length(results)) do
        printf(1,"%3s: %,d - %s\n",results[i])
    end for
end procedure

show(extract_names())
