在 Python 中解析 CSS

kke*_*y18 5 python regex

我正在合并 100 个 HTML 页面,所有页面的头部都嵌入了样式元素。使用 BeautifulSoup 提取 style 的内容,但现在只剩下将字符串解析为字典 {selector_str:properties_str} 的任务。查看tinycss,它可以轻松地为我提供选择器“.c0”,但不是属性字符串“{...}”。

这是一个示例字符串

'.c0 { padding: 1px 0px 0px; font-size: 11px } .c1 { margin: 0px; font-size: 11px } .c2 { font-size: 11px } .c3 { font-size: 11px; font-style: italic; font-weight: bold } '
Run Code Online (Sandbox Code Playgroud)

建议?欢迎使用正则表达式。这就是 CSS 的范围。每个页面上的类选择器 .c0 到 .c100(s) 都遵循相同的模式。

kke*_*y18 0

这是我降落的地方。使用了 BadKarma 的策略,即用劈叉来破解琴弦。

from bs4 import BeautifulSoup
import re

class RichText(BeautifulSoup):
    """
    subclass BeautifulSoup
    add behavior for generating selectors and declaration_blocks from <style>
    """

    def __init__(self, html_page):
        super().__init__(html_page)

    @property
    def rules_as_str(self):
        return str(self.style.string)

    def rules(self):
        split_rules = re.split('(\.c[0-9]*)', self.rules_as_str)
        # side effect of split, first element is null
        assert(split_rules[0] == '')
        # enforce that it MUST be null, then pass over it
        for i in range(1, len(split_rules), 2):
            yield (split_rules[i].strip(), split_rules[i+1].strip())


if __name__ == '__main__':

    with open('rich-text.html', 'r') as f:
        html_file = f.read()

    rich_text = RichText(html_file)
    for selector, declaration_block in rich_text.rules():
        print(selector)
        print(declaration_block)

>>> with open("test.py") as f:
...     code = compile(f.read(), "test.py", 'exec')
...     exec(code)
... 
.c0
{ padding: 1px 0px 0px; font-size: 11px }
.c1
{ margin: 0px; font-size: 11px }
.c2
{ font-size: 11px }
.c3
{ font-size: 11px; font-style: italic; font-weight: bold }
>>> 
Run Code Online (Sandbox Code Playgroud)