Better way to extract country wise player list from html file using regex Problem statement:

Make country wise player list from the following html code

HTML CODE:

&lt;ul&gt;
    &lt;li&gt;
        Australia
        &lt;ol&gt;
            &lt;li&gt;Steven Smith&lt;/li&gt;
            &lt;li&gt;David Warner&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;
        Bangladesh
        &lt;ol&gt;
            &lt;li&gt;Mashrafe Mortaza&lt;/li&gt;
            &lt;li&gt;Tamim Iqbal&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/li&gt;
    &lt;li&gt;
        England
        &lt;ol&gt;
            &lt;li&gt;Eoin Morgan&lt;/li&gt;
            &lt;li&gt;Jos Buttler&lt;/li&gt;
        &lt;/ol&gt;
    &lt;/li&gt;
&lt;/ul&gt;


Expected Output:

Australia- Steven Smith, David Warner

Bangladesh- Mashrafe Mortaza, Tamim Iqbal

England- Eoin Morgan, Jos Buttler

My Code:

import re

with open('playerlist.html', 'r') as f:
    text = f.read()

mytext = re.sub(r'[\n\t]', '', text)

pat = r'&lt;li&gt;(\w+?)&lt;ol&gt;&lt;li&gt;(\w+\s?\w+)&lt;/li&gt;&lt;li&gt;(\w+\s?\w+)&lt;/li&gt;'

cpat = re.compile(pat)

result = cpat.findall(mytext)


for a,b,c in result:
    print('{0}- {1}, {2}'.format(a,b,c))
Regular expressions is not the right tool when it comes to parsing HTML. There are specialized HTML parsers that would do a better job resulting into a more robust and less fragile solution. 

Just to name a few problems that exists in your current approach:


what if there are more than two players for a country
what if there are 0 players for a country
what if a country name contains a space or a single quote
what if a player's name consists of more than two words or contains a single quote
what if there are newlines after the opening or before the closing li tag


Instead, you may, for instance, use BeautifulSoup library:

from bs4 import BeautifulSoup


with open('playerlist.html', 'r') as input_file:
    soup = BeautifulSoup(input_file, "html.parser")


for country in soup.select("ul &gt; li"):
    country_name = country.find(text=True, recursive=False).strip()
    players = [player.get_text(strip=True) for player in country.select("ol &gt; li")]

    print('{country} - {players}'.format(country=country_name,
                                         players=', '.join(players)))