Создание таблицы из файла txt

Есть файл txt, содержащий список чертежей деталей и сборочных чертежей, полученный путём shift+ПКМ -> Копировать как путь. Его примерная структура (1200+ строк):

1 812.04.20.1062 - Кронштейн нижний (1370).pdf
812.04.29.0001А - подкладка под ключ.pdf
04.01 812.04.06.0100 СБ - Щит АВ (Ц 293).pdf
04.01 812.04.06.0100Б СБ - Щит 200-93 (Ц 293).pdf
04.01 812.04.06.0100Б - Щит АВ.pdf
04.01 812.04.06.0101Б - Щит Сенсорный.pdf
04.01.01 812.04.18.0101 (изм. 1) - Щит АВ (П Л 1100 244 Вент).pdf
04.01.01 812.24.01.0101 - Щит Сенсорный (500).pdf
04.01.02 812.04.06.0102 - Крепление Линзы Сенсора.pdf

Я хочу сделать таблицу с полями:

  • Серийный номер: начинается на 812, например 812.04.20.1062
  • Наименование: пример "Кронштейн нижний"
  • Вид: после серийного номера в некоторых чертежах стоит метка СБ, это значит что чертеж сборочный, соответственно поле Вид может иметь значения "СБ" или "Деталь"
  • Изменение: в некоторых чертежах есть метка "изм. 1" - это значит что в чертеж вносили изменения, это тоже надо учитывать в отдельном поле
  • Подсказка: оно тоже есть не у всех чертежей, указывается в конце в скобках, например "(П Л 1100 244 Вент)"

В названиях есть определенный шаблон, в целом я справился. Вот моя реализация:

with open('/content/drive/My Drive/ColabNotebooks/resources/details.txt', 'r') as file:
    content = file.read().split('\n')
    content = [(line[line.find('812'):]) for line in content]

    for line in content:
        serial_number = line[:line.find(' ')]

        if line.find('СБ') == -1:
            type_doc = 'Деталь'
        else:
            type_doc = 'СБ'

        name = line[line.find('-') + 2:]

        hint = name.find('(')
        if hint == -1:
            hint = 0
        else:
            hint = name[hint:]
            name = name[:name.find('(')]


        change = line.find('изм.')
        if change == -1:
            change = 0
        else:
            change = line[change:change + 6].rstrip(')')


        print(f'{serial_number:15}|{name:20}|{type_doc:6}|{change:6}|{hint}')

Вывод:

812.04.81.1713 |Деталь|     0|Отбойник            |(456)
812.04.02.1720 |СБ    |     0|Вставка в отбойник  |0

1200 строк обрабатываются за 5-7 секунд, но я думаю, это из-за подключения к google drive (пишу код в google colab, т.к. нет возможности установить среду на рабочий ПК). Расширение .pdf и некоторые другие вещи я удалял в самом файле через "Заменить всё".

Мне кажется, это какое-то уродство, я делал что называется в лоб. Есть более лаконичный способ? В идеале с помощью Pandas, чтобы я мог записать всё это в CSV. (хочу научиться работать с Pandas в том числе)


Ответы (1 шт):

Автор решения: Алексей Р

Можно прочесть весь исходный файл сразу во фрейм и потом разобрать его с помощью регулярных выражений.

df = pd.read_table(r'c:\test\data.txt', header=None)
df['Серийный номер'] = df[0].str.extract(r'(812\S+)')  # выбираем серийники, наиная с 812 и до первого пробельного символа
df['Наименование'] = df[0].str.extract(r'-\s*(.+)\.pdf')[0].str.replace('\([^()]+?\)', '', regex=True)  # выбираем наименование как любые симовлы от - до .pdf и удаляем все скобочные группы
df['Вид'] = df[0].str.extract(r'812\S+\s*(СБ)')  # выбираем сочетание СБ после серийника
df['Изменение'] = df[0].str.extract(r'812\S+\s*\((изм\..+?)\)')  # выбиранем содержимое скобочной группы, если в ней есть изм.
df['Подсказка'] = df[0].str.extract(r'\(([^)]+)\)\.pdf')  # выбираем содержимое скобочной группы перед .pdf

df = df.fillna('-')  # заменяем отсутствующие данные прочерками (дефисами). Если str.extract (выше) на находит нужных данных, то ставит NaN
print(df)
                                                                   0   Серийный номер             Наименование Вид Изменение          Подсказка
0                     1 812.04.20.1062 - Кронштейн нижний (1370).pdf   812.04.20.1062        Кронштейн нижний    -         -               1370
1                           812.04.29.0001А - подкладка под ключ.pdf  812.04.29.0001А       подкладка под ключ   -         -                  -
2                       04.01 812.04.06.0100 СБ - Щит АВ (Ц 293).pdf   812.04.06.0100                  Щит АВ   СБ         -              Ц 293
3                  04.01 812.04.06.0100Б СБ - Щит 200-93 (Ц 293).pdf  812.04.06.0100Б              Щит 200-93   СБ         -              Ц 293
4                                 04.01 812.04.06.0100Б - Щит АВ.pdf  812.04.06.0100Б                   Щит АВ   -         -                  -
5                          04.01 812.04.06.0101Б - Щит Сенсорный.pdf  812.04.06.0101Б            Щит Сенсорный   -         -                  -
6  04.01.01 812.04.18.0101 (изм. 1) - Щит АВ (П Л 1100 244 Вент).pdf   812.04.18.0101                  Щит АВ    -    изм. 1  П Л 1100 244 Вент
7                  04.01.01 812.24.01.0101 - Щит Сенсорный (500).pdf   812.24.01.0101           Щит Сенсорный    -         -                500
8              04.01.02 812.04.06.0102 - Крепление Линзы Сенсора.pdf   812.04.06.0102  Крепление Линзы Сенсора   -         -                  -
→ Ссылка