使用Beautiful Soup将CSS属性转换为单独的HTML属性?

时间:2012-05-01 16:47:05

标签: python html css html-parsing beautifulsoup

我正在尝试编写一个程序,该程序将采用HTML文件并使其更加适合电子邮件。现在所有转换都是手动完成的,因为没有一个在线转换器完全符合我们的需要。

这听起来像是一个很好的机会来突破我的编程知识的极限并实际编写一些有用的东西,所以我提议尝试在业余时间编写一个程序来帮助使这个过程更加自动化。

我对HTML或CSS了解不多,所以我主要依靠我的兄弟(知道HTML和CSS)来描述这个程序需要做出哪些改变,所以如果我问一个傻瓜,请耐心等待我题。这对我来说是一个全新的领域。

大多数更改都非常基础 - 如果您看到标记/属性X然后将其转换为标记/属性Y.但是在处理包含样式属性的HTML标记时遇到了麻烦。例如:

<img src="http://example.com/file.jpg" style="width:150px;height:50px;float:right" />

我希望尽可能将样式属性转换为HTML属性(或将样式属性转换为更适合电子邮件的内容)。所以在转换后它应该是这样的:

<img src="http://example.com/file.jpg" width="150" height="50" align="right"/>

现在我意识到并非所有CSS样式属性都具有HTML等价物,所以现在我只想专注于那些。我掀起了一个可以进行转换的Python脚本:

from bs4 import BeautifulSoup
import re

class Styler(object):

    img_attributes = {'float' : 'align'}

    def __init__(self, soup):
        self.soup = soup

    def format_factory(self):
        self.handle_image()

    def handle_image(self):
        tag = self.soup.find_all("img", style = re.compile('.'))
        print tag
        for i in xrange(len(tag)):
            old_attributes = tag[i]['style']
            tokens = [s for s in re.split(r'[:;]+|px', str(old_attributes)) if s]
            del tag[i]['style']
            print tokens

            for j in xrange(0, len(tokens), 2):
                if tokens[j] in Styler.img_attributes:
                    tokens[j] = Styler.img_attributes[tokens[j]]

                tag[i][tokens[j]] = tokens[j+1]

if __name__ == '__main__':
    html = """
    <body>hello</body>
    <img src="http://example.com/file.jpg" style="width:150px;height:50px;float:right" />
    <blockquote>my blockquote text</blockquote>
    <div style="padding-left:25px; padding-right:25px;">text here</div>
    <body>goodbye</body>
    """
    soup = BeautifulSoup(html)
    s = Styler(soup)
    s.format_factory()

现在这个脚本会很好地处理我的特定示例,但它不是非常强大,我意识到,当遇到现实世界的例子时,它很容易破解。我的问题是,我怎样才能使这个更强大?据我所知,Beautiful Soup没有办法改变或提取样式属性的各个部分。我猜这就是我要做的事。

2 个答案:

答案 0 :(得分:8)

对于这类事情,我建议将HTML解析器(如BeautifulSoup或lxml)与专门的CSS解析器结合使用。我在the cssutils package取得了成功。您可以比尝试使用正则表达式来匹配任何可能在野外找到的CSS更容易。

例如:

>>> import cssutils
>>> css = 'width:150px;height:50px;float:right;'
>>> s = cssutils.parseStyle(css)
>>> s.width
u'150px'
>>> s.height
u'50px'
>>> s.keys()
[u'width', u'height', u'float']
>>> s.cssText
u'width: 150px;\nheight: 50px;\nfloat: right'
>>> del s['width']
>>> s.cssText
u'height: 50px;\nfloat: right'

因此,使用它可以非常轻松地提取和操作所需的CSS属性,并使用BeautifulSoup将它们直接插入到HTML中。但是,请注意cssText属性中弹出的换行符。我认为cssutils更适合将事物格式化为独立的CSS文件,但它足够灵活,主要用于你在这里做的事情。

答案 1 :(得分:1)

使用stoneage包http://pypi.python.org/pypi/StoneageHTML

而不是重新发明轮子