Отслеживаем изменения в doc и docx при помощи Python
Здравствуйте, уважаемые коллеги! Прошу не судить строго, так как это моя первая статья.
У нас появилась необходимость отслеживать изменения в doc и docx файлах с фиксацией имени пользователя, который внес эти изменения. Сами файлы находятся в расшаренной папке (да, да, общие папки это зло, но убедить у меня не получилось) и необходимо знать кто внес изменения. Подробнее под катом.
Сами изменения в файлах будем отслеживать при помощи watchdog (pip install watchdog).
Код для отслеживания всех изменений:
# Для отслеживания изменений
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
# Отслеживаем изменения
class Watcher:
def __init__(self, path):
self.observer = Observer()
self.path = path
def run(self):
event_handler = Handler()
self.observer.schedule(event_handler, self.path, recursive=True)
self.observer.start()
try:
while True:
time.sleep(1)
except:
self.observer.stop()
print("Error")
self.observer.join()
class Handler(FileSystemEventHandler):
@staticmethod
def on_any_event(event):
if event.is_directory:
return None
print(
"[{}] noticed: [{}] on: [{}] ".format(
time.asctime(), event.event_type, event.src_path
)
)
if __name__ == "__main__":
w = Watcher('C:\\Users\\user\\Desktop\\')
w.run()
Такой код позволяет отслеживать изменения во всех файлах (не показывая кто изменил) на рабочем столе пользователя. Естественно, папку «C:\Users\user\Desktop\» эту указал для примера.
Пример вывода:
[Mon Dec 5 14:32:37 2022] noticed: [modified] on: [C:\Users\user\Desktop\Документ Microsoft Word.docx]
Тут нет информации о том, кто изменил файл. Эту информацию можно получить из самого docx файла.
Нам нужно отслеживать изменения именно в doc и docx файлах, поэтому переделаем код:
# -*- coding: utf-8 -*-
# Для атрибутов файла
import docx
# Для отслеживания изменений
import time
from watchdog.observers import Observer
from watchdog.events import FileSystemEventHandler
# Отслеживаем изменения
class Watcher:
def __init__(self, path):
self.observer = Observer()
self.path = path
def run(self):
event_handler = Handler()
self.observer.schedule(event_handler, self.path, recursive=True)
self.observer.start()
try:
while True:
time.sleep(1)
except:
self.observer.stop()
print("Error")
self.observer.join()
class Handler(FileSystemEventHandler):
@staticmethod
def on_any_event(event):
# if event.is_directory:
# return None
# print(
# "[{}] noticed: [{}] on: [{}] ".format(
# time.asctime(), event.event_type, event.src_path
# )
# )
# Получаем атрибуты файла
if '.tmp' in event.src_path:
return None
try:
document = docx.Document(docx = event.src_path)
core_properties = document.core_properties
print(f'{core_properties.last_modified_by} в {core_properties.modified} модифицировал файл {event.src_path}')
except:
pass
if __name__ == "__main__":
w = Watcher('C:\\Users\\user\\Desktop\\')
w.run()
В данном примере изменения просто печатаются в консоль при помощи строки:
print (f'{core_properties.last_modified_by} в {core_properties.modified} модифицировал файл {event.src_path}')
Пример вывода:
Иванов Иван Иванович в 2022–12–05 07:35:00 модифицировал файл C:\Users\user\Desktop\Документ Microsoft Word.docx
Для журналирования можно использовать простейшую запись в файл:
f = open('change-doc.log','w') # открытие в режиме записи
f.write(f'{core_properties.last_modified_by} в {core_properties.modified} модифицировал файл {event.src_path}\n') # запись в файл
f.close() # закрытие файла
Или можно отправлять изменения на почту (если это востребовано):
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
fromaddr = "test@mail.ru"
toaddr = "test2@mail.ru"
mypass = "password"
msg = MIMEMultipart()
msg['From'] = fromaddr
msg['To'] = toaddr
msg['Subject'] = f'Модифицирован файл {event.src_path}'
body = f'{core_properties.last_modified_by} в {core_properties.modified} модифицировал файл {event.src_path}'
msg.attach(MIMEText(body, 'plain'))
server = smtplib.SMTP_SSL('smtp.mail.ru', 465)
server.login(fromaddr, mypass)
text = msg.as_string()
server.sendmail(fromaddr, toaddr, text)
server.quit()
Также приведу полный список атрибутов docx файла, которые можно таким же образом получить:
file_name = 'C:\\Users\\user\\Desktop\\123.docx'
document = docx.Document(docx = file_name)
core_properties = document.core_properties
print('author', core_properties.author)
print('created', core_properties.created)
print('last_modified_by', core_properties.last_modified_by)
print('last_printed', core_properties.last_printed)
print('modified', core_properties.modified)
print('revision', core_properties.revision)
print('title', core_properties.title)
print('category', core_properties.category)
print('comments', core_properties.comments)
print('identifier', core_properties.identifier)
print('keywords', core_properties.keywords)
print('language', core_properties.language)
print('subject', core_properties.subject)
print('version', core_properties.version)
print('keywords', core_properties.keywords)
print('content_status', core_properties.content_status)
Спасибо за внимание!!!