Python selectolax tutorial

Selectolax is Python binding to Modest engine - fast HTML5 parser with CSS selectors. It is really fast, it can be used to parse HTML just like BeautifulSoup4 but again, it is much much faster than Beautifulsoup4

Installation #

From PyPI using pip:

pip install selectolax

Or you can install the development version from github:

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

API usage #

Import selectolax

from selectolax.parser import HTMLParser

Say we have html document like this:

html = """
<body>
    <span id="vspan"></span>
    <h1>Welcome to selectolax tutorial</h1>
    <div id="text">
        <p class='p3' style='display:none;'>Excepteur <i>sint</i> occaecat cupidatat non proident</p>
        <p class='p3' vid>Lorem ipsum</p>
    </div>
    <div>
        <p id='stext'>Lorem ipsum dolor sit amet, ea quo modus meliore platonem.</p>
    </div>
</body>
"""

Select all p tags with class p3 #

selector = "p.p3"

for node in HTMLParser(html).css(selector):
    print('---------------------')
    print('Node: %s' % node.html)
    print('attributes: %s' % node.attributes)
    print('node text: %s' % node.text(deep=True, separator='', strip=False))
    print('tag: %s' % node.tag)
    print('parent tag: %s' % node.parent.tag)
    if node.last_child:
        print('last child inside current node: %s' % node.last_child.html)
    print('---------------------\n')

Output:

---------------------
Node: <p class="p3" style="display:none;">Excepteur <i>sint</i> occaecat cupidatat non proident</p>
attributes: {'class': 'p3', 'style': 'display:none;'}
node text: Excepteur sint occaecat cupidatat non proident
tag: p
parent tag: div
last child inside current node:  occaecat cupidatat non proident
---------------------

---------------------
Node: <p class="p3" vid="">Lorem ipsum</p>
attributes: {'class': 'p3', 'vid': None}
node text: Lorem ipsum
tag: p
parent tag: div
last child inside current node: Lorem ipsum
---------------------

Select first match #

print("H1: %s" % HTMLParser(html).css_first('h1').text())

Output:

H1: Welcome to selectolax tutorial

Default return value if there is no matches #

print("Title: %s" % HTMLParser(html).css_first('title', default='not-found'))

Output:

Title: not-found

Strictly one match #

HTMLParser(html).css_first("p.p3", default='not-found', strict=True)

Error will be raised:

---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-6-7a26563add76> in <module>
----> 1 HTMLParser(html).css_first("p.p3", default='not-found', strict=True)

~/Projects/python/selectolax/selectolax/parser.pyx in selectolax.parser.HTMLParser.css_first()

~/Projects/python/selectolax/selectolax/node.pxi in selectolax.parser.Node.css_first()

ValueError: Expected 1 match, but found 2 matches

Nested selectors #

HTMLParser(html).css_first('div#text').css_first('p:nth-child(2)').html

Output:

<p class="p3" vid="">Lorem ipsum</p>'

Iterate over all nodes on the current level #

for node in HTMLParser(html).css("div#text"):
    for cnode in node.iter():
        print(cnode.tag, cnode.html)

Output:

-text 
        
p <p class="p3" style="display:none;">Excepteur <i>sint</i> occaecat cupidatat non proident</p>
-text 
        
p <p class="p3" vid="">Lorem ipsum</p>
-text 

Tag removal #

html_parser = HTMLParser(html)
for node in html_parser.tags('p'):
    node.decompose()
print(html_parser.body.html)

Output:

<body>
    <span id="vspan"></span>
    <h1>Welcome to selectolax tutorial</h1>
    <div id="text">
        
        
    </div>
    <div>
        
    </div>

</body>

Tag unwrapping #

print(html)

Output:

<body>
    <span id="vspan"></span>
    <h1>Welcome to selectolax tutorial</h1>
    <div id="text">
        <p class='p3' style='display:none;'>Excepteur <i>sint</i> occaecat cupidatat non proident</p>
        <p class='p3' vid>Lorem ipsum</p>
    </div>
    <div>
        <p id='stext'>Lorem ipsum dolor sit amet, ea quo modus meliore platonem.</p>
    </div>
</body>
html_parser = HTMLParser(html)
html_parser.unwrap_tags(['p', 'i'])
print(html_parser.body.html)

<body>
    <span id="vspan"></span>
    <h1>Welcome to selectolax tutorial</h1>
    <div id="text">
        Excepteur sint occaecat cupidatat non proident
        Lorem ipsum
    </div>
    <div>
        Lorem ipsum dolor sit amet, ea quo modus meliore platonem.
    </div>

</body>
Attribute manip

Attribute manipulation #

html_parser = HTMLParser(html)
node = html_parser.css_first('div#text')
node.attrs['data'] = 'secrect data'
node.attrs['id'] = 'new_id'
print(node.attributes)
del node.attrs['id']
print(node.attributes)
print(node.html)

{'data': 'secrect data', 'id': 'new_id'}
{'data': 'secrect data'}
<div data="secrect data">
        <p class="p3" style="display:none;">Excepteur <i>sint</i> occaecat cupidatat non proident</p>
        <p class="p3" vid="">Lorem ipsum</p>
    </div>

Tree traversal #

html_parser = HTMLParser(html)
for node in html_parser.root.traverse():

    if node.tag == '-text':
        text = node.text(deep=True).strip()
        if text:
            print(text)
    else:
        print(node.tag)

Output:


-undef
html
head
body
span
h1
Welcome to selectolax tutorial
div
p
i
sint
occaecat cupidatat non proident
p
Lorem ipsum
div
p
Lorem ipsum dolor sit amet, ea quo modus meliore platonem.

Tags:

Python