3

I have an HTML file with following code inside:

<...some tags...>
<textarea id="123" attributeX="4" attributeY="5" style="width:159px; height:50px; other styles;">
<textarea id="456" attributeX="4" attributeY="5" style="width:135px; height:50px; other styles;">
<textarea id="789" attributeX="4" attributeY="5" style="width:177px; height:50px; other styles;">
<...some other tags...>

I want to change the width of all textareas to 200px by the use of Python 2.0. My first idea was to use BeautifulSoup and I found this code snippet:

from bs4 import BeautifulSoup
from cssutils import parseStyle

html = '<td style="font-size: .8em; font-family: monospace; background-color: rgb(244, 244, 244);"></td>'

soup = BeautifulSoup(html, 'html.parser')
style = parseStyle(soup.td['style'])
style['background-color'] = 'red'
soup.td['style'] = style.cssText
print(soup.td)

Unfortunately, this only changes the style of one tag. I want to change all textarea tags

I tried the following code:

from bs4 import BeautifulSoup
from cssutils import parseStyle

soup = BeautifulSoup(sHTML,'html.parser')
for txt in soupfindAll('textarea'):
   style = parseStyle(text.textarea['style'])
   style['width'] = '200px'
   txt.textarea['style'] = style.cssText

This generates a "NoneType object is not subscriptable" error on the line "style = ..."

Does anyone have an idea how I can perform the required formatting?

Thanks

1
  • If possible, replace all of the inline styles with an external stylesheet, then you won't have to resort to an HTML parser just to change a width property. As for your code, where might soupfindAll be defined? Is this really soup.findAll? (prefer soup.find_all). Also, prefer lxml to html.parser. txt is different than text; maybe you have a typo? Commented Feb 24, 2022 at 2:13

1 Answer 1

1

Try the following approach:

from bs4 import BeautifulSoup
from cssutils import parseStyle

with open('input.html') as f_html:
    soup = BeautifulSoup(f_html, 'html.parser')
    
for textarea in soup.find_all('textarea', style=True):
    style = parseStyle(textarea['style'])
    style['width'] = '200px'
    textarea['style'] = style.cssText.replace('\n', ' ')

with open('output.html', 'w', encoding='utf-8') as f_html:
    f_html.write(str(soup))

So if your HTML is:

<html>
<body>
<textarea id="123" attributeX="4" attributeY="5" style="width:159px; height:50px;"></textarea>
<textarea id="456" attributeX="4" attributeY="5" style="width:135px; height:50px;"></textarea>
<textarea id="789" attributeX="4" attributeY="5" style="width:177px; height:50px;"></textarea>
<textarea id="789" attributeX="4" attributeY="5"></textarea>
</body>
</html>

The output would become:

<html>
<body>
<textarea attributex="4" attributey="5" id="123" style="width: 200px; height: 50px"></textarea>
<textarea attributex="4" attributey="5" id="456" style="width: 200px; height: 50px"></textarea>
<textarea attributex="4" attributey="5" id="789" style="width: 200px; height: 50px"></textarea>
<textarea attributex="4" attributey="5" id="789"></textarea></body>
</html>

Here the final <textarea> is unchanged as there was no style. If required, this could be added as follows:

from bs4 import BeautifulSoup
from cssutils import parseStyle

with open('input.html') as f_html:
    soup = BeautifulSoup(f_html, 'html.parser')
    
for textarea in soup.find_all('textarea'):
    if 'style' in textarea.attrs:
        # Update existing style
        style = parseStyle(textarea['style'])
        style['width'] = '200px'
        textarea['style'] = style.cssText.replace('\n', ' ')
    else:
        # Add missing style
        textarea['style'] = 'width: 200px; height: 50px'

with open('output.html', 'w', encoding='utf-8') as f_html:
    f_html.write(str(soup))
Sign up to request clarification or add additional context in comments.

2 Comments

This is exactly what I wanted! Nevertheless, you mentioned it is possible to enforce applying the style if a tag doesn't have the style attribute at all. Can you please tell me, how I can do that?
No problem, I have added a version that can do that too

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.