-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpdf-diff.py
More file actions
166 lines (136 loc) · 7.46 KB
/
Copy pathpdf-diff.py
File metadata and controls
166 lines (136 loc) · 7.46 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
import fitz # PyMuPDF
import difflib
def extract_text_from_pdf(file_path):
doc = fitz.open(file_path)
pages_text = []
for page_num in range(len(doc)):
page = doc.load_page(page_num)
text = page.get_text()
pages_text.append(text)
return pages_text
def highlight_differences(pdf1_path, pdf2_path, output_path):
doc1 = fitz.open(pdf1_path)
pdf1_pages = extract_text_from_pdf(pdf1_path)
pdf2_pages = extract_text_from_pdf(pdf2_path)
# Keep track of highlighted instances to avoid duplicates
highlighted_instances = set()
for page_num, (text1, text2) in enumerate(zip(pdf1_pages, pdf2_pages)):
if text1 != text2:
# Use difflib to find differences line by line
diff = list(difflib.ndiff(text1.splitlines(), text2.splitlines()))
page = doc1.load_page(page_num)
# Track lines that have been removed, added, or moved
removed_lines = set()
added_lines = set()
changed_lines = []
# Collect removed and added lines
for line in diff:
if line.startswith("- "):
removed_lines.add(line[2:].strip())
elif line.startswith("+ "):
added_lines.add(line[2:].strip())
# Detect moved lines and changed lines
moved_lines = removed_lines.intersection(added_lines)
removed_lines -= moved_lines # Remove moved lines from the removed set
added_lines -= moved_lines # Remove moved lines from the added set
# Identify changed lines
sm = difflib.SequenceMatcher(None, text1.splitlines(), text2.splitlines())
for tag, i1, i2, j1, j2 in sm.get_opcodes():
if tag == 'replace':
for i in range(i1, i2):
changed_lines.append(text1.splitlines()[i].strip())
for line in diff:
print(line) # Print each line of the diff output
# Initialize variables to prevent uninitialized color usage
color = None
note_content = ""
# Check for moved lines first
if line.startswith("- ") or line.startswith("+ "):
text_to_highlight = line[2:].strip()
if text_to_highlight in moved_lines:
color = (0, 0, 1) # Blue for moved lines
note_content = "Moved line: Found in a different position"
# Check for changed lines next
elif line.startswith("- ") and text_to_highlight in changed_lines:
color = (1, 1, 0) # Yellow for changed lines
note_content = f"Changed line: Original was '{text_to_highlight}'"
# Check for added lines after that
elif line.startswith("+ "):
text_to_highlight = line[2:].strip()
if text_to_highlight in added_lines:
color = (0, 1, 0) # Green for added lines
# Finally, check for removed lines
elif line.startswith("- "):
text_to_highlight = line[2:].strip()
if text_to_highlight in removed_lines:
color = (1, 0, 0) # Red for removed lines
note_content = "Removed line: Not present in the second PDF"
# Highlight only if a color has been set
if color is not None:
# Search for the text in the page and highlight it
print(f"Searching for: '{text_to_highlight}' on page {page_num + 1}")
text_instances = page.search_for(text_to_highlight)
for inst in text_instances:
if inst not in highlighted_instances: # Check if already highlighted
annot = page.add_highlight_annot(inst)
annot.set_colors(stroke=color) # Set the highlight color
annot.update()
if note_content: # Add note if present
annot.set_info(title="Note", content=note_content)
highlighted_instances.add(inst) # Mark this instance as highlighted
else:
print(f"No match found for: '{text_to_highlight}' on page {page_num + 1}")
print(f"Differences highlighted on page {page_num + 1}.")
# Save the annotated PDF
doc1.save(output_path)
print(f"Annotated PDF saved as '{output_path}'.")
def log_differences_to_file(pdf1_path, pdf2_path, output_txt_path):
pdf1_pages = extract_text_from_pdf(pdf1_path)
pdf2_pages = extract_text_from_pdf(pdf2_path)
with open(output_txt_path, "w", encoding="utf-8") as log_file:
for page_num, (text1, text2) in enumerate(zip(pdf1_pages, pdf2_pages)):
if text1 != text2:
# Use difflib to find differences line by line
diff = list(difflib.ndiff(text1.splitlines(), text2.splitlines()))
log_file.write(f"Page {page_num + 1}:\n")
print(f"Page {page_num + 1}:\n") # Print to terminal
line_number = 1
i = 0
while i < len(diff):
line = diff[i]
text_to_highlight = line[2:].strip()
# Check for changed lines with context indicators
if line.startswith("- ") and (i + 1 < len(diff) and diff[i + 1].startswith("? ")):
original_line = text_to_highlight
new_line = diff[i + 2][2:].strip()
# Check if there's a change indicator
if (diff[i + 1].startswith("? ")):
log_entry = f" Line {line_number}: '{new_line}' replaced '{original_line}'\n"
log_file.write(log_entry)
print(log_entry, end="") # Print to terminal
i += 4 # Skip the next two lines (the new line and the change indicator)
line_number += 1
continue
# Check for removed lines
elif line.startswith("- "):
log_entry = f" Line {line_number}: Removed line -> '{text_to_highlight}'\n"
log_file.write(log_entry)
print(log_entry, end="") # Print to terminal
# Check for added lines
elif line.startswith("+ "):
log_entry = f" Line {line_number}: Added line -> '{text_to_highlight}'\n"
log_file.write(log_entry)
print(log_entry, end="") # Print to terminal
line_number += 1
i += 1 # Move to the next line in the diff
log_file.write("\n") # Separate different pages for clarity
print() # Print a newline for better readability in terminal
log_file.write("Comparison complete.\n")
print("Comparison complete.\n") # Print completion message to terminal
# Specify paths
pdf1_path = "1.pdf"
pdf2_path = "4.pdf"
output_path = "output_annotated.pdf"
output_txt_path = "differences_log.txt"
# highlight_differences(pdf1_path, pdf2_path, output_path)
log_differences_to_file(pdf1_path, pdf2_path, output_txt_path)