################### From html5-parser ################### .. package-meta:: html5-parser kovidgoyal/html5-parser `html5-parser `_ wraps gumbo, the C WHATWG parser, and hands the result back as an `lxml `_/ElementTree tree. It is a parse-only front end: gumbo tokenizes and tree-builds in C, then the nodes are copied into whatever backend you pick with ``treebuilder`` (``lxml`` by default, or ``lxml_html``, ``etree``, ``dom``, ``soup``). Everything after the parse — querying, mutation, serialization — is the chosen backend's job, not html5-parser's. It ships in `calibre `_ and is a common drop-in wherever a WHATWG-correct tree is wanted inside an existing lxml pipeline. turbohtml covers the same ground with a single library: it parses the same WHATWG tree in its own C engine, then keeps you inside a fully typed :class:`~turbohtml.Document` for querying, editing, and serialization, with no ``libxml2`` or gumbo build dependency to carry. *************************** turbohtml vs html5-parser *************************** .. list-table:: :header-rows: 1 :widths: 16 42 42 - - Dimension - turbohtml - html5-parser - - Scope - Parse, query, mutate, and serialize in one library - Parse only; the returned tree is handed to lxml/etree/dom/soup for everything else - - Feature breadth - CSS :meth:`~turbohtml.Node.select`, XPath 1.0 :meth:`~turbohtml.Node.xpath`, the :meth:`~turbohtml.Node.find`/:meth:`~turbohtml.Node.find_all` grammar, a full edit surface, Markdown/plain-text renderers, sanitizer, linkifier, structured-data extraction - Whatever the selected backend exposes (lxml's XPath/cssselect, ElementTree's API, BeautifulSoup's, minidom's) - - Performance - Native C engine straight into the native tree; see the table below - Native gumbo parse copied into a libxml2/backend tree - - Typing - Fully type annotated with bundled stubs - Untyped; static types come from the chosen backend (e.g. lxml-stubs) - - Dependencies - Self-contained C extension, no ``libxml2``/gumbo - Links ``libxml2`` and bundles gumbo; the default path also needs ``lxml`` - - Maintenance - Actively developed - Stable and maintained by the calibre author, low churn Feature overlap =============== Both are native WHATWG parsers with no pure-Python pass, so the parse call and the tree walk port directly: - ``html5_parser.parse(markup)`` for ``str`` or ``bytes`` input maps to :func:`turbohtml.parse`. - Encoding control (``transport_encoding``/``fallback_encoding``) maps to the ``encoding`` and ``detect_encoding`` arguments of :func:`turbohtml.parse`. - The root element (``return_root=True``, the default) is :attr:`doc.root `. - XPath 1.0 querying is at parity: ``root.xpath(...)`` maps to :meth:`~turbohtml.Node.xpath`, and both stop at XPath 1.0 with EXSLT (libxml2 has no XPath 2.0/XQuery either). - Element accessors port exactly as in the :ref:`From lxml ` section, since html5-parser returns lxml's tree: ``el.get``/``el.attrib`` become :attr:`~turbohtml.Element.attrs`, ``el.getparent()`` becomes :attr:`~turbohtml.Node.parent`. What turbohtml adds =================== - CSS selection built in: :meth:`~turbohtml.Node.select`/:meth:`~turbohtml.Node.select_one` plus the :meth:`~turbohtml.Node.find`/:meth:`~turbohtml.Node.find_all` filter grammar, with no ``lxml.cssselect`` detour. - A full mutation surface on the typed tree, so edits do not require pulling in libxml2 semantics. - Serialization in the same library: the :attr:`~turbohtml.Node.html` property, :meth:`~turbohtml.Node.encode`, and the :class:`~turbohtml.Markdown`/:class:`~turbohtml.PlainText`/:class:`~turbohtml.Html` renderers. - Text extraction as first-class API: :attr:`~turbohtml.Node.text`, :attr:`~turbohtml.Node.strings`, :attr:`~turbohtml.Node.stripped_strings`. - A real ``