Парсим CSS стили на Python

Парсим CSS стили на Python

Люди, которые создают HTML файлы не всегда пишут стили CSS в отдельный файл. Очень часто внутри тегов в самом HTML коде можно наблюдать конструкции вида style="какие-то стили". Это не является чем-то неправильным, но когда все стили в CSS файле - код гораздо более читаем. Я решил написать утилиту на Python которая ищет в файле index.html стили, не вынесенные в отдельный CSS файл и выносит их туда, заменяя конструкциями вида class="имя класса". На вход программы подаётся Index.html, на выходе получаем index2.html и css.css. Чтобы index2.html работал как оригинал, нужно вручную подключить к нему созданный css.css. Пожалуйста не забудьте это сделать вручную, иначе у вас создастся впечатление что скрипт не работает. Сперва я думал, что задача замены style="что-то" на class="имя класса" с вынесением стилей в css.css довольно просто решится обычным replace. Но в жизни всё оказалось сложнее - так как у тегов уже могут быть какие-то классы, и нужно сперва проверить есть ли они, и если есть дописать добавляемый класс через пробел, а если никаких классов нет то добавить в тег конструкцию class="наш класс". Пришлось задействовать модуль парсинга Beautful soup. Устанавливаем его: pip install beautifulsoup4 Далее я приведу код программы с комментариями

import re
import bs4

f = open("index.html","rb")
s = f.read()
s = s.decode('utf-8',errors='ignore')

# Прочитали HTML файл в переменную s

soup = bs4.BeautifulSoup(s, "html.parser")
s=str(soup)
match = re.findall("style=\"(.*?)\"", s)
# Удаляем повторяющиеся элементы
match = dict(zip(match, match)).values()

# Распарсили стили в match

if not(match is None):
    ii = 1
    cs=""
    for ss in match:
        soup = bs4.BeautifulSoup(s, "html.parser")
        s=str(soup)
        ds="style=\"" + ss + "\""
        newname = "class=\"cl" + str(ii) + "\""
        # получаем имя класса куда парсим текущий стиль
        clasn = "cl" + str(ii)
        # получаем список тегов с этими стилями       
        tutu = soup.findAll(style=ss)

        flag=0
        for tgs in tutu:
            
            clname = tgs.get('class',None)

            # Проверяем есть ли класс в теге
            if(clname==None):
                s = s.replace(ds, newname)
            else:
                clnm=""
                for tgn in clname:
                    clnm=clnm+" "+tgn
                clnm=clnm.strip()
                tgs2=str(tgs)
                tgs2 = tgs2.replace(" " + ds, "")
                tgs2 = tgs2.replace("class=\"" + clnm + "\"", "class=\"" + clnm + " " + clasn + "\"")
                s = s.replace(str(tgs), tgs2)
                
        ss = ss.replace("; ",";\n")
        cs = cs + "\n.cl" + str(ii) + "{\n" + ss + "\n}"
        ii = ii + 1
f.close()

qq = open("css.css","w")
qq.write(cs)
qq.close()

f2 = open("index2.html","wb")
# Чистим код от закрывающих тегов которые добавил bs4
s = s.replace("</link>","")
s = s.replace("</meta>","")
s = s.replace("</hr>","")
s = s.replace("</input>","")
s = s.replace("</img>","")
s = s.replace("</br>","")
s = s.replace("</p>","")
s = s.encode('utf-8',errors='ignore')
f2.write(s)
f2.close()
Beautiful Soup зачем-то пытается закрыть непарные теги и это проблема. Я постарался удалить закрывающие теги которые он понаставил, но если вдруг чего-то пропустил - добавьте правило для замены нужного тега пустой строкой.

Парсим CSS стили на Python Лого Pythono.ru Парсим CSS стили на Python