from bs4 import BeautifulSoup, Tag class Attribute(object): def __init__(self, attrname, attrvalue): 'Initializes a new attribute.' self._attrname = attrname self._attrvalue = attrvalue @property def name(self): 'The attribute name' return self._attrname @property def value(self): 'The attribute value' return self._attrvalue class TagFactory(object): 'A factory for `bs4.Tag` objects' def __init__(self, soup): 'Initializes a new factory given a `bs4.BeautifulSoup`.' self._soup = soup @property def soup(self): 'The `bs4.BeautifulSoup` instance.' return self._soup def __call__(self, tagname, *contents, **kwargs): 'Instantiates a `bs4.BeautifulSoup` instance given contents.' tag = None for c in contents: if type(c) is Attribute: if tag is not None: raise ValueError('Attribute cannot follow content') kwargs[c.name] = c.value else: if tag is None: tag = self.soup.new_tag(tagname, **kwargs) tag.append(c) if tag is None: tag = self.soup.new_tag(tagname, **kwargs) return tag soup = BeautifulSoup('') f = TagFactory(soup) html = f('html', f('head', f('meta', Attribute('foo', 'bar')) ), f('body', f('h1', 'Hello World!'), f('p', 'This is a test.') ) ) print(html.prettify())