selectolax

rushterMIT活跃维护

基于 Modest 和 Lexbor 引擎的 Python HTML5 解析库,解析速度快,支持 CSS 选择器,适合网页抓取时高效提取页面数据。

Python binding to Modest and Lexbor engines. Fast HTML5 parser with CSS selectors for Python.

v1.0.2发布于 2026-10-22 15:17 UTC1,714star +1 / 7 天95fork同步于 2026-11-10 11:47 UTC

怎么上手

由 README 提炼,执行前请确认
pip install selectolax
硬件要求按 README 说明

README 未说明,纯 CPU 解析,无 GPU 或显存要求

下载:源码 zip·GitHub Releases(安装包)本站不镜像安装包

项目说明

由 README 自动翻译提炼

用 Cython 封装 Lexbor 引擎的 Python HTML5 解析器,带 CSS 选择器,解析速度远超 Beautiful Soup

基于 Modest 和 Lexbor 引擎的 Python HTML5 解析库,解析速度快,支持 CSS 选择器,适合网页抓取时高效提取页面数据。

核心能力

  • 基于 Lexbor 引擎解析 HTML5,Cython 编写
  • 支持 css_first 和 css 按 CSS 选择器取节点
  • 支持 nth-child、:not、:has 等高级选择器
  • 提供 lexbor-contains 伪类按文本内容匹配
  • 可读取节点 text、attributes、tag、parent 和 html

容易踩的坑

安装因编译报错时需改装 pip install selectolax[cython];从 GitHub 装开发版要 git clone --recursive 拉取子模块;旧版本配新版 Python 容易编译失败

内容由模型根据 README 生成,可能不完整或不准确,以官方文档为准。看原文 README

最近发版

5 个版本v1.0.2
  1. v1.0.2最新正式版2026-10-22 · 2026-10-22 15:17 UTC

    Bugfix release for 1.0.1.

    • Fix insert_child(), insert_before(), insert_after() and replace_with() move nodes.
    • Add the move parameter to insert_child(), insert_before(), insert_after() and replace_with(). Pass move=True to move the node instead of copying it: the node is removed from its current position and placed in the new one. A node taken from another parser is copied into the target document and removed from the document it came from. The default is move=False, which keeps the copying behaviour.
  2. v1.0.12026-10-17 · 2026-10-17 17:53 UTC
    查看更新说明
    • Add the scripting option to LexborHTMLParser, which parses <noscript> the way a browser with scripting enabled does: its content becomes raw text, so a <noscript> in <head> no longer pushes the head elements after it into <body>. The default is unchanged.
    • Add template_fragments() for reaching the content of <template> elements which are ignored by HTML5 compliant parsers.
    • Do not replace <-undef> it not longer possible to get it.
    • The internal <html> wrapper of an HTML fragment is no longer reported as the parent of the fragment's top-level nodes.
    • create_tag() no longer returns None for the tags whose start tag the HTML parser drops (html, head, body, caption, col, colgroup, frame, frameset, tbody, td, tfoot, th, thead, tr).
    • Fix inner_html covering only the first top-level node of an HTML fragment.
    • Improve the speed of comment extraction
    • Improve the speed of len(attrs) by counting the attribute list directly
    • Fix encoding initialization when encoding=True.
  3. v1.0.02026-10-03 · 2026-10-03 15:01 UTC
    查看更新说明

    This release contains breaking changes. It focuses on speed improvements and corner cases.

    The main change is that the Modest backend is no longer available. It is outdated and unmaintained since 2021, contains bugs, and does not follow modern HTML5 standards. We have supported the Lexbor backend since 2021, and we have recommended it for more than 3 years. It gets updated every month and follows all the modern HTML5 standards while being faster on a lot of tasks.

    The second is that parse_fragment() is gone. It re-implemented fragment parsing by guessing whether the input was a document or a fragment; LexborHTMLParser(html, is_fragment=True) already does this properly, so the guessing layer has been removed.

    The rest of the changes fix corner cases where the bugs were happening rarely, usually when heavily modifying the tree.

    • Breaking: Remove the Modest backend. selectolax.parser is now a stub that raises ImportError on import. Use the lexbor backend (from selectolax.lexbor import LexborHTMLParser) instead.
    • Breaking: Remove parse_fragment().
    • Breaking: Fix css_matches and any_css_matches missing matches outside the first top-level node of an HTML fragment. They now search the same scope as css.
    • Breaking: Fix tags and strip_tags doing nothing on an HTML fragment. tags returned an empty list and strip_tags removed nothing, because the fragment was not reachable from the document node.
    • Breaking: Fix the internal <html> wrapper of an HTML fragment being reported as a match.
    • Breaking: Fix scripts_contain and script_srcs_contain missing matches outside the first top-level node of an HTML fragment. They now search the same scope as css.
    • Breaking: Fix scripts_contain and script_srcs_contain answering from another scope's cached result. The cache is keyed by the node the search is rooted at rather than the node it was called on.
    • Breaking: Fix select() missing matches outside the first top-level node of an HTML fragment. It now searches the same scope as css.
    • Breaking: Fix traverse() covering only the first top-level node of an HTML fragment, and yielding nothing when the fragment starts with a text node.
    • Breaking: Fix attribute_longer_than and any_attribute_longer_than returning inconsistent results
    • Breaking: attributes and attrs now report an attribute's qualified name instead of its local name. An element carrying both href and xlink:href used to collapse them into a single href key.
    • Breaking: Fix iter() skipping the remaining children when a node is removed during iteration
    • Breaking: Fix an HTML fragment whose first node is text dropping the rest of the fragment. LexborHTMLParser('a<span>s</span>', is_fragment=True).text() returned 'a' instead of 'as'.
    • Fix text() silently returning truncated text instead of raising when a fragment fails to be collected.
    • Fix scripts_contain and script_srcs_contain sometimes returning wrong results due to HTML mutations.
    • Fix a single undecodable byte in an untrusted document making html, inner_html, html_pretty, attributes, attrs, id, tag, text_lexbor and text_content raise UnicodeDecodeError. Bytes Lexbor passes through verbatim are now substituted with U+FFFD, the way text() already did.
    • Fix text_lexbor sometimes holding temporary memory longer than needed
    • Improve memory consumption, potential stack overflow and slow extraction in merge_text_nodes(). It is now up to 10 times faster.
    • Improve speed of __eq__
    • Improve speed of attrs.items() and attrs.values().
    • Fix the inner_html setter attaching element children to non-element nodes
    • Fix head and body dangling after setting inner_html on the <html> element
    • Fix the inner_html setter freeing the replaced children
    • Fix root going stale on an HTML fragment.
    • Fix a se
  4. v0.4.132026-09-29 · 2026-09-29 08:20 UTC
    查看更新说明
    • Support lexbor-only builds with --disable-modest
    • Importing selectolax no longer automatically imports selectolax.parser and selectolax.lexbor
    • Update lexbor
  5. v0.4.122026-09-18 · 2026-09-18 07:56 UTC
    查看更新说明
    • Add options parameter to LexborHTMLParser to pass Lexbor document parsing options (for example, LexborDocumentOptions.WO_EVENTS to disable mutation events). Fixes #221.
    • Fix LexborHTMLParser.clone() losing nodes for empty HTML fragments
    • Allow empty elements in text_lexbor. Fixes #220.
    • Update lexbor

用户点评

登录用户的真实使用记录,可按版本和硬件筛选
共 0 条

    还没有人点评。第一个说出真实体验的人最有价值。

    README 原文

    未翻译

    selectolax logo


    A fast HTML5 parser with CSS selectors, written in Cython, using the Lexbor engine.


    PyPI - Version PyPI Total Downloads CI GitHub License


    Installation

    From PyPI using pip:

    pip install selectolax
    

    If installation fails due to compilation errors, you may need to install Cython:

    pip install selectolax[cython]
    

    This usually happens when you try to install an outdated version of selectolax on a newer version of Python.

    Development version from GitHub:

    git clone --recursive  https://github.com/rushter/selectolax
    cd selectolax
    pip install -r requirements_dev.txt
    python setup.py install
    

    How to compile selectolax while developing:

    make clean
    make dev
    

    Basic examples

    Here are some basic examples to get you started with selectolax:

    Parsing HTML and extracting text:

    from selectolax.lexbor import LexborHTMLParser
    
    html = """
    <h1 id="title" data-updated="20201101">Hi there</h1>
    <div class="post">Lorem Ipsum is simply dummy text of the printing and typesetting industry. </div>
    <div class="post">Lorem ipsum dolor sit amet, consectetur adipiscing elit.</div>
    """
    tree = LexborHTMLParser(html)
    
    print(tree.css_first('h1#title').text())
    # 'Hi there'
    
    print(tree.css_first('h1#title').attributes)
    # {'id': 'title', 'data-updated': '20201101'}
    
    print([node.text() for node in tree.css('.post')])
    # ['Lorem Ipsum is simply dummy text of the printing and typesetting industry. ',
    #  'Lorem ipsum dolor sit amet, consectetur adipiscing elit.']
    

    Using advanced CSS selectors

    from selectolax.lexbor import LexborHTMLParser
    
    html = "<div><p id=p1><p id=p2><p id=p3><a>link</a><p id=p4><p id=p5>text<p id=p6></div>"
    selector = "div > :nth-child(2n+1):not(:has(a))"
    
    for node in LexborHTMLParser(html).css(selector):
        print(node.attributes, node.text(), node.tag)
        print(node.parent.tag)
        print(node.html)
    # {'id': 'p1'}  p
    # div
    # <p id="p1"></p>
    # {'id': 'p5'} text p
    # div
    # <p id="p5">text</p>
    
    Using lexbor-contains CSS pseudo-class to match text
    from selectolax.lexbor import LexborHTMLParser
    html = "<div><p>hello </p><p id='main'>lexbor is AwesOme</p></div>"
    parser = LexborHTMLParser(html)
    # Case-insensitive search
    results = parser.css('p:lexbor-contains("awesome" i)')
    # Case-sensitive search
    results = parser.css('p:lexbor-contains("AwesOme")')
    assert len(results) == 1
    assert results[0].text() == "lexbor is AwesOme"
    

    Simple Benchmark

    • Extract title, links, scripts and a meta tag from main pages of top 754 domains. See examples/benchmark.py for more information.
    PackageTime
    Beautiful Soup (html.parser)61.02 sec.
    lxml / Beautiful Soup (lxml)9.09 sec.
    html5_parser16.10 sec.
    selectolax (Lexbor)2.39 sec.

    Links

    License

    Contributors

    Thanks to all the contributors of selectolax!