BeautifulSoup find all elements with class and replace each value, then print the joined new list

Viewed 515

There should be a simple "pythonic" resolve for my issue.

I got a BeautifulSoup from where I'm extracting the text from elements with class

<ul>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Red</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Black</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Blue</a>
    </li>
</ul>

Using find_all, I'm extracting the text, then I join the values with a comma, then I print. What I'm trying to do is to replace the values (the colors) with different values.

categories = soup.find_all('li',{'class':'category'})
for i in range(len(categories)):
    if categories[i] == 'Red':
        categories[i] = '1'
    if categories[i] == 'Black':
        categories[i] = '2'
    if categories[i] == 'Blue':
        categories[i] = '3'

output = ','.join([i.text for i in categories])
print(output)

The result is:

Red,Black,Blue

So what I get are the initial values, no replacements, and I can't figure out why. I feel there's something very simple I'm missing and it drives me nuts!

======== SOLUTION

Based on @fazlul's answer below, I've modified a bit to make it more modular. The solution would be:

categories = [t.get_text(strip=True) for t in soup.find_all('li',{'class':'category'})]
    for i in range(len(categories)):
        if categories[i] == 'Red':
            categories[i] = '1'
        if categories[i] == 'Black':
            categories[i] = '2'
        if categories[i] == 'Blue':
            categories[i] = '3'
    output = ','.join([i for i in categories])
    print(output)

Result is:

1,2,3
3 Answers

I'm getting the following output:

from bs4 import BeautifulSoup

html_doc="""
<ul>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Red</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Black</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Blue</a>
    </li>
</ul>
"""

soup = BeautifulSoup(html_doc, 'html.parser')

categories = categories = [t.get_text(strip=True).replace('Red','1').replace('Black','2').replace('Blue','3')for t in soup.find_all('li',{'class':'category'})]

print(categories)

Output:

['1', '2', '3']

a solution with select and a dict for your replacement

categories = soup.select('li.category a')
cat_dict={'Red':1, 'Black':2, 'Blue':3}

for i, cat in enumerate(categories):
    categories[i] = cat_dict[cat.text]
print(categories)

The more robust way to go about it is to create a lookup dictionary. Otherwise, you'll need to code out every possible color/text within the list in the the html, and or have an extremely long bit of code as your list comprehension.

See below:

from bs4 import BeautifulSoup

html_doc="""
<ul>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Red</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Black</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Blue</a>
    </li>
    <li class="category">
        <i class="fa icon-cat"></i>
        <a href="#">Green</a>
    </li>
</ul>
"""


lookup_dict = {'Red':'1',
            'Black':'2',
            'Blue':'3'}

soup = BeautifulSoup(html_doc, 'html.parser')

categories = [lookup_dict.get(t.text.strip(), t.text.strip()) for t in soup.find_all('li',{'class':'category'})]
print(categories)
Related