Электронная медицинская карта -собираем анализы

от автора

Небольшой пост о том, как собрать в единый pdf все записи о сданных анализах в поликлинике из электронной медицинской карты. Данные располагаются на сайте (https://lk.emias.mos.ru/medical-records), однако пользоваться ими неудобно, так как на сайте все свалено в несколько pdf куч. И, чтобы посмотреть, все позиции по анализам, сданным, например, в один день, необходимо заходить в каждую из этих куч и смотреть только эту одну позицию. Итого можно посмотреть до 15 pdf с анализами, сданных в один день. А уж если хочется за несколько дней посмотреть результаты анализов, умножай на n и затем вручную сравнивай!

В качестве опции также будет осуществлен вывод табличных данных из pdf в excel.

Выглядит все это примерно следующим образом:

Нажимая на стрелочку вниз, предлагается скачивать файлы pdf и далее их изучать вручную.

За два года может накопиться до 125 файлов и в них легко запутаться, так как при скачивании они принимают одинаковые имена, а об их дате можно узнать, лишь открыв их.

Что будет делать программа ?

Программа будет «заходить» на сайт медкарты, позволяя пользователю ввести только код из смс (необходимое требование при регистрации на сайте), находить раздел с анализами, «проваливаться» туда, скачивать все pdf. Далее, исходя из дат сдачи анализов, программа разложит их по папкам с соответствующей датой, склеит в каждой папке все файлы в один pdf.
В итоговом pdf файле программа выделит цветом, если есть отклонение:

Во второй части мини-проекта будет осуществлен вывод всех данных из всех pdf с анализами в единую excel таблицу с использованием несколько различных подходов.

Приступаем.

Импорты библиотек:

import webbrowser,time from selenium import webdriver from selenium.webdriver.common.keys import Keys from selenium.webdriver.firefox.options import Options import shutil import PyPDF2, os import fitz 

*При установке модуля fitz, может потребоваться модуль PyMuPDF. При установке последнего (pip install PyMuPDF) можно столкнуться с ошибкой «error: Microsoft Visual C++ 14.0 is required. Get it with „Microsoft Visual…“ Чтобы ее обойти можно попробовать установить модуль следующим образом: „pip install —only-binary :all: PyMuPDF“.

Заходить на сайт будем с помощью модуля selenium и браузера chrome. Поэтому все настройки для них:

options = webdriver.ChromeOptions() options.add_argument("start-maximized") # options.add_argument("--headless") options.add_experimental_option("excludeSwitches", ["enable-automation"]) options.add_experimental_option('useAutomationExtension', False) browser = webdriver.Chrome(options=options) #browser = webdriver.Firefox(options=options) browser.get ('https://lk.emias.mos.ru/medical-records') time.sleep (5) 

*Для запуска браузера может потребоваться chromedriver. Если web-страница не открывается программой и вылетает с ошибкой, в которой присутствует chromedriver — обновите chromedriver, скачайте версию для своего браузера.

Далее идет блок авторизации на сайте медкарты, проходящий через сайт mos.ru.
Программа сама вбивает логин и пароль в нужные поля (эти поля необходимо предварительно заполнить в программе), нажимает кнопку „Войти“. Однако, так как требуется еще и ввести код из смс на странице, пользователю необходимо ввести его вручную на сайте, когда появится соответствующее сообщение. В оболочке, в которой работает программа python, также необходимо нажать любую кнопку, чтобы программа продолжила работу:

act = browser.find_element_by_id('login') for i in 'login@yandex.ru':         act.send_keys(i)         time.sleep (0.1) act = browser.find_element_by_id('password') for i in 'password':         act.send_keys(i)         time.sleep (0.1) act = browser.find_element_by_id('bind').click() x=input('Введите код sms на странице и нажмите любую кнопку здесь') 

Переход на сайте в раздел с анализами и переход в директорию на диске, куда будет производиться сохранение:

act = browser.find_element_by_css_selector('#analyzes_card_open_button > div > span') act.click() time.sleep(3) act = browser.find_element_by_css_selector('#analyzes_card_all > div > span') act.click() time.sleep(3) cwd = os.path.join(os.path.expandvars("%userprofile%"),"Downloads") os.chdir(cwd) 

Основной цикл программы

Теперь программа будет брать дату на сайте перед каждой записью анализа и создавать
одноименную папку на диске. Скачивать без подтверждения pdf с сайта, а так как директория скачивания едина для всех файлов (задана при создании browser), то еще и перемещать каждый pdf в целевую директорию с помощью shututil.

#переходим в папку для скачивания и скачиваем, создавая папки по датам x=0 try:         while True:                 text=browser.find_element_by_xpath('/html/body/div[1]/div[1]/div[3]/div[2]/div/div[2]/div[1]/div[1]/div[2]/div[3]/div/div[3]/div[2]/div/div['+str(x+1)+']/span').text                                                 if not os.path.exists(text):                         os.makedirs(text)                                                act=browser.find_element_by_css_selector('#analyzes_list_download-'+str(x)+' > div > svg')                 act.click()                 time.sleep(2)                                  for root, dirs, files in os.walk("."):                             for file in files:                                 if file.endswith('pdf'):                                                                         try:                                                 shutil.move(file, text) #перенос файла в целевую директорию                                         except:                                                 pass                                  x+=1 except:         pass 

В результате должны появиться папки с датами сдачи анализов, а внутри папок — все анализы, сданные в эту дату:

Вспомогательные функции

Создадим функцию, которая склеит все pdf в один файл.

#работаем с текстом в файлах def join_pdfs():         pdfFiles = []                 for filename in os.listdir('.'):             if filename.endswith('.pdf'):                 pdfFiles.append(filename)         pdfFiles.sort()         pdfWriter = PyPDF2.PdfFileWriter()         # Loop through all the PDF files.         for filename in pdfFiles:             pdfFileObj = open(filename, 'rb')             pdfReader = PyPDF2.PdfFileReader(pdfFileObj)             # Loop through all the pages and add them.             for pageNum in range(0, pdfReader.numPages):                 pageObj = pdfReader.getPage(pageNum)                 pdfWriter.addPage(pageObj)         # Save the resulting PDF to a file.         pdfOutput = open('all.pdf', 'wb')         pdfWriter.write(pdfOutput)         pdfOutput.close() 

А также функцию, которая подсветит желтым маркером результаты анализа, если есть отклонения. Здесь просто поиск по тексту искомой фразы.

def highlight():         #помечаем отклонения в файле all.pdf желтым цветом и сохраняем как highlighted_text.pdf         with fitz.open('all.pdf') as doc:                 for page in doc:                         areas = page.searchFor("отклонение от")                         page.addHighlightAnnot(areas)                         doc.save("highlighted_text.pdf") 

Теперь применим созданные функции ко всем папкам с анализами.

for root, dirs, files in os.walk("."):                 for i in dirs:                                 os.chdir(i)                 join_pdfs()                 highlight()                 os.chdir('..') 

В результате в каждой папке создается файл all.pdf и файл highlighted_text.pdf, в которых собраны результаты, а во втором файле еще и подсвечены отклонения.

Сформируем единую таблицу excel, собрав данные из таблиц pdf

Для этих целей воспользуемся двумя сторонними пакетами и посмотрим, насколько корректно они обработают таблицы в pdf файлах с анализами.

Первый пакет — camelot —

pip install camelot-py[cv]

Для работы с ним также придется установить стороннее приложение ghostscript и добавить его в PATH (например, C:\gostscript\gs9.55.0\bin).

Сама программа выглядит так:

import os import shutil import pandas as pd  df1 = pd.DataFrame()   for root, dirs, files in os.walk("."):                 for i in dirs:                                 os.chdir(i)                 date_my = {'Тест': i} #добавили дату в датафрейм                 df1=df1.append(date_my,ignore_index=True)                 for root, dirs, files in os.walk("."):                         for file in files:                                 if file.endswith('.pdf'):                                         print(file)                                                                                 tables = camelot.read_pdf(file)                                         print("Total tables extracted:", tables.n)                                                                                 for n in range(len(tables)):                                                 df1=df1.append(tables[n].df[1:],ignore_index=True)#добавили датафрейм                                                                  os.chdir('..') df1.to_excel('out1.xlsx',header=False, index=False) 

Camelot создает датафреймы, которые понимает pandas. В данном случае мы первоначально создали свой датафрейм, далее добавили в него строку с датой сдачи анализов в целом и, далее, в цикле добавили все извлеченные таблицы из всех pdf.

По непонятным причинам camelot обрабатывает не все pdf c табличными данными и из некоторых файлов не извлекает таблицы, несмотря на то, что структурно файлы схожи между собой:

Тем не менее, результат для извлеченных данных неплохой:

Теперь посмотрим на альтернативный пакет — tabula.

pip install tabula-py

Он также требует установки дополнительного ПО, в данном случае java (jre). Путь к последней, также необходимо добавить в PATH (Например, C:\Program Files (x86)\Java\jre1.8.0_221\bin).

Текст программы схож с предыдущей:

import tabula #https://www.thepythoncode.com/article/extract-pdf-tables-in-python-camelot #tabula-py #необходима java (jre), путь к которой доваить в PATH - C:\Program Files (x86)\Java\jre1.8.0_221\bin #выводит итоговый результат из всех директорий в out2.xlsx  import csv,os import shutil import pandas as pd  df1 = pd.DataFrame()   for root, dirs, files in os.walk("."):                 for i in dirs:                 #print(i)                 #print(os.getcwd())                 os.chdir(i)                 date_my = {'Тест': i} #добавили дату в датафрейм                 df1=df1.append(date_my,ignore_index=True)                 for root, dirs, files in os.walk("."):                         for file in files:                                 if file.endswith('.pdf'):                                         if file=='Определение ГГТ-γ-глютамилтрансферазы.pdf':                                                 os.rename(file, 'Определение ГГТ-глютамилтрансферазы.pdf')                                                 file='Определение ГГТ-глютамилтрансферазы.pdf'                                         print(file)                                         tables = tabula.read_pdf(file, pages="all")                                         df1=df1.append(tables,ignore_index=True)#добавили датафрейм                 os.chdir('..') df1.to_excel('out2.xlsx',header=False, index=False) 

Обработка pdf идет также, через преобразование таблиц в датафреймы.

Tabula обработала в итоге все файлы pdf, даже те, что не смог camelot. Однако в excel таблицы
отобразились не идеально:

На этом все, теперь можно наслаждаться результатами анализов, созерцая все вместе.
Надеюсь, программы окажутся полезными. Хотя бы до тех пор, пока в личном кабинете электронной медицинской карты не появится схожий функционал.

Скачать программы — здесь.


ссылка на оригинал статьи https://habr.com/ru/articles/581424/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *