Comparing two HTML files using Python difflib package

Viewed 1573

I am having issues with comparing two HTML files using Pythob difflib. While I was able to generate a comparison file that highlighted any changes, when I opened the comparison file, it displayed the raw HTML and CSS script/tags instead of the plain text.

E.g

<Html><Body><div class="a"> Text Here</div></Body></html>

instead of

Text Here

My Python Script is as follows:

import difflib

file1 = open('file1.html', 'r').readlines()
file2 = open('file2.html', 'r').readlines()
diffHTML = difflib.HtmlDiff()
htmldiffs = diffHTML.make_file(file1,file2)

with open('Comparison.html', 'w') as outFile:
     outFile.write(htmldiffs)

My input files looks something like this

                    <!DOCTYPE html>
            <html>
                    <head>
                        <title>Text here</title>        
                    <style type="text/css">
            @media all {
                h1 {
                    margin: 0px;
                    color: #222222;
                }
                #page-title {
                    color: #222222;
                    font-size: 1.4em;
                    font-weight: bold;
                }
                body {
                    font: 0.875em/1.231 tahoma, geneva, verdana, sans-serif;
                    padding: 30px;
                    min-width: 800px;
                }
                .divider {
                    margin: 0.5em 15% 0.5em 10%;
                    border-bottom: 1px solid #000;
                }
                
                }
                .section.header {
                    background-color: #303030;
                    color: #ffffff;
                    font-weight: bold;
                    margin: 0 0 5px 0;
                    padding: 5px 0 5px 5px;
                }
                .section.subheader {
                    background-color: #CFCFCF;
                    color: #000;
                    font-weight: bold;
                    padding: 1px 5px;
                    margin: 0px auto 5px 0px;
                }
                
            
        
                .response_rule_prefix {
                    font-style: italic;
                }

                .exception-scope
                {
                    color: #666666;
                    padding-bottom: 5px;
                }

                .where-clause-header
                {
                    color:#AAAA99;
                }

                .section {
                    padding: 0em 0em 1.2em 0em;
                }

                #generated-Time {
                    padding-top:5px;
                    float:right;
                }
                #page-title, #generated-Time {
                    display: inline-block;
                }
            

        
            </style></head>

                    <body>
            <div id="title-section" class="section ">
                            <div id="page-branding">
                                <h1>Title</h1>
                            </div>
                            <div id="page-title">
                                Sub title
                            </div>
                            <div id="generated-Time">
                                Date & Time : Jul 2, 2020 2:42:48 PM
                            </div>
            </div>

                <div class="section header">General</div>
                <div id="general-section" class="section">
                <div  class="general-detail-label-container">
                    <label id="policy-name-label">Text here</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-name-content" >Text here</span>
                </div>
                <div  class="general-detail-label-container">
                    <label id="policy-description-label">Description A :</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-description-content""></span>Text here</span>
                </div>
                <div  class="general-detail-label-container">
                    <label id="policy-label-label" class="general-detail-label">Description b:</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-label-content" class="wrapping-text"></span>
                </div>
                <div  class="general-detail-label-container">
                    <label id="policy-group-label" class="general-detail-label">Group:</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-group-content" class="wrapping-text">Text here</span>
                </div>
                <div  class="general-detail-label-container">
                    <label id="policy-status-label" class="general-detail-label">Status:</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-status-content">
                            <label id="policy-status-message">Active</label>
                        </span>
                </div>
                <div  class="general-detail-label-container">
                    <label id="policy-version-label" class="general-detail-label">Version:</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-version-content" class="wrapping-text">7</span>
                </div>
                <div  class="general-detail-label-container">
                    <label id="policy-last-modified-label" class="general-detail-label">Last Modified:</label>
                </div>
                <div class="general-detail-content-container">
                        <span id="policy-last-modified-content" class="wrapping-text">Jun 15, 2020 2:41:48 PM</span>
                </div>
                </div>

                </body>
            </html>
1 Answers

Assuming that you are only looking for the text changes and not changes to the HTML, you could strip the output of HTML after the comparison. There are a number of ways to achieve this. The two that I first thought of was:

  1. RegEx, because this is native in Python, and
  2. BeautifulSoup, because it was created to read webpages

Create a function, using either of above methods, to strip the output of HTML

e.g. using BeautifulSoup

UPDATE

Reading through the documentation again, it seems to me that the comparison will yield the actual HTML too, however, you could create an additional output that only shows the text changes.

Also to avoid showing the whole document, I've set the context parameter to True

Using BeautifulSoup

import re
import difflib
from bs4 import BeautifulSoup

def remove_html_bs(raw_html):
    data = BeautifulSoup(raw_html, 'html.parser')
    data = data.findAll(text=True)
    
    def visible(element):
        if element.parent.name in ['style', 'script', '[document]', 'head', 'title']:
            return False
        elif re.match('<!--.*-->', str(element.encode('utf-8'))):
            return False
        return True
    
    result = list(filter(visible, data))

    return result

def compare_files(file1, file2):
    "Creates two comparison files"
    file1 = file1.readlines()
    file2 = file2.readlines()
    
    # Difference line by line - HTML
    difference_html = difflib.HtmlDiff(tabsize=8).make_file(file1, file2, context=True, numlines=5)
    # Difference line by line - raw
    difference_file = set(file1).difference(file2)
    
    # List of differences by line index
    difference_index = []
    for dt in difference_file:
        for index, t in enumerate(file1):
            if dt in t:
                difference_index.append(f'{index}, {remove_html_bs(dt)[0]}, {remove_html_bs(file2[index])[0]}')

    # Write entire line with changes
    with open('comparison.html', 'w') as outFile:
        outFile.write(difference_html)

    # Write only text changes, by index
    with open('comparison.txt', 'w') as outFile:
        outFile.write('LineNo, File1, File2\n')
        outFile.write('\n'.join(difference_index))

    return difference_html, difference_file


file1 = open('file1.html', 'r')
file2 = open('file2.html', 'r')

difference_html, difference_file = compare_files(file1, file2)
Related