Skip to content Skip to sidebar Skip to footer

Disable Special "class" Attribute Handling

The Story: When you parse HTML with BeautifulSoup, class attribute is considered a multi-valued attribute and is handled in a special manner: Remember that a single tag can have m

Solution 1:

What I don't like in this approach is that it is quite "unnatural" and "magical" involving importing "private" internal _htmlparser. I hope there is a simpler way.

Yes, you can import it from bs4.builder instead:

from bs4 import BeautifulSoup
from bs4.builder import HTMLParserTreeBuilder

class MyBuilder(HTMLParserTreeBuilder):
    def __init__(self):
        super(MyBuilder, self).__init__()
        # BeautifulSoup, please don't treat "class" as a list
        self.cdata_list_attributes["*"].remove("class")


soup = BeautifulSoup(data, "html.parser", builder=MyBuilder())

And if it's important enough that you don't want to repeat yourself, put the builder in its own module, and register it with register_treebuilders_from() so that it takes precedence.


Solution 2:

The class HTMLParserTreeBuilder is actually declared on the upper module _init__.py, so there is no need to import directly from the private submodule. That said I would do it the following way:

import re

from bs4 import BeautifulSoup
from bs4.builder import HTMLParserTreeBuilder

bb = HTMLParserTreeBuilder()
bb.cdata_list_attributes["*"].remove("class")

soup = BeautifulSoup(bs, "html.parser", builder=bb)
found_elements = soup.find_all(class_=re.compile(r"^name\-single name\d+$"))
print found_elements

It is basically the same as defining the class as in the OP (maybe a bit more explicit), but I don't think there is a better way to do it.


Post a Comment for "Disable Special "class" Attribute Handling"