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

Моя цель - предложение широкого ассортимента товаров и услуг на постоянно высоком качестве обслуживания по самым выгодным ценам.

Прежде чем перейти к статье, хочу вам представить, экономическую онлайн игру Brave Knights, в которой вы можете играть и зарабатывать. Регистируйтесь, играйте и зарабатывайте!


Небольшой пост о том, как собрать в единый 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/post/581424/


Интересные статьи

Интересные статьи

ВведениеВ данной статье я бы хотел рассмотреть проблему обновления PHP в виртуальной машине BitrixVM, и действия, которые возможно применить если выполнение переезда на машину с обновленным ПО невозмо...
Часто от программистов PHP можно услышать: «О нет! Только не „Битрикс“!». Многие специалисты не хотят связываться фреймворком, считают его некрасивым и неудобным. Однако вакансий ...
Есть статьи о недостатках Битрикса, которые написаны программистами. Недостатки, описанные в них рядовому пользователю безразличны, ведь он не собирается ничего программировать.
В одном из подкастов недавно услышал про сервис отзывов Capterra, на котором собраны проверенные отзывы пользователей о программном обеспечении. Повинуясь профессиональному интересу, решил тщател...
С первым же взглядом на эту занятную вещицу рождается сразу несколько очевидных каламбуров и про то, что «буквально наружу выворачивает», и про «носимые игрушки», и про одежду, которая обнажает, ...