2016-05-16 1 views
0

Мне нужно извлечь таблицы из файла (.csv или .txt), предположим, что файл является csv . В этом файле различаются разные размеры (500x5, 200x3, ...) Мне нужно извлечь их в другом массиве, чтобы загрузить их в базу данныхИзвлечь массив с другим размером из файла

структура моего файла:

Book of sales du 01/01/2014 au 31/12/2050;;;;;;;;;;; 

Sales;;;;;;;;;;; 

Date;Invoice;Client;Txt;Price 

19/02/2015;1;Johnny;coloris: 002, taille: 54/18;82,03€ 

21/02/2015;2;Florian;coloris: 005PL, taille: 56/17;78,34€ 
Total;;;;10 700,74€ 

;;;;;;;;;;; 

Avoirs générés;;;;;;;;;;; 

Date;N° Avoir;Client 

04/03/2015;1;Johnny 

28/03/2015;2;Jacques-Elie 

Total;;698,45€ 

Не могли бы вы мне помочь, пожалуйста?

ответ

0

Для обработки этих данных вам нужно будет написать простой синтаксический анализатор.

Парсер - это небольшой конечный автомат. В зависимости от текущего состояния и ввода, которое он видит дальше, он переходит в новое состояние. Когда он перемещается между состояниями, он собирает входы и создает какую-то древовидную структуру. Вы можете попытаться визуализировать это, рисуя круги для каждого состояния и линии, соединяющие их, когда я описываю состояния, которые должен пройти ваш парсер. Обозначьте каждую строку с помощью ввода, необходимого для перемещения между состояниями.

Ваши данные начинаются в исходном состоянии (ожидание заголовка), ожидая строку заголовка с диапазоном дат:

Book of sales du 01/01/2014 au 31/12/2050;;;;;;;;;;; 

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

Ваши таблицы, похоже, начинаются с имени, за которым следуют 11 точек с запятой. Например:

Sales;;;;;;;;;;; 

Если вы обнаружили окончание строки с 11 точкой с запятой, то вам нужно, чтобы начать новую таблицу с заданным именем таблицы и перейти в состояние (ожидая имена полей).

Имена полей являются строки, разделенные точкой с запятой:

Date;Invoice;Client;Txt;Price 

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

Ваши данные практически такой же, как заголовок, будучи значения полей, разделенных точкой с запятой:

19/02/2015;1;Johnny;coloris: 002, taille: 54/18;82,03€ 

Опять же, вы прочитали, раскол и сохранить. На этот раз вы остаетесь в текущем состоянии (данные обработки), так как в таблице может быть более одной записи.

Сводная строка для таблицы имеет те же поля, с Total вместо Дата в этом случае:

Total;;;;10 700,74€ 

Так что если вы видите строку, начинающуюся с «Total» в то время как в (обработка данных), вы переход в состояние (сводка) и сохранение итогов.

Из (резюме), вы переход к (конец таблицы), которая представляет собой линию с запятой:

;;;;;;;;;;; 

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

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

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

Аналогично, если ввести понятие пустой таблицы, мы можем упростить наш синтаксический анализатор, поскольку нам не нужно состояние (конечная таблица). Мы рассматриваем его как начало пустой таблицы без заголовков, данных или резюме. Достаточно легко игнорировать пустые таблицы, когда мы закончили разбор. Кроме того, мы можем притвориться, что первая таблица начинается после пустой таблицы, поэтому мы можем начать с состояния (обработки данных) и все будет хорошо.

Пустые строки между каждой строкой на вашем входе (возможно, возврат каретки + перевод строки из окон) могут быть удалены.

Собираем вместе, анализатор становится:

with open file: 
    # transition to (awaiting header) 
    read header 
    # transition to (processing data) 
    current table = empty 
    for each line: 
     # strip blank 
     if blank: # blank does not change state 
      continue 
     if new table line: 
      # transition to (new table) 
      save current table if any 
      make new table and set it to current table 
      # transition to (processing data) 
     else: 
      # transition to (processing data) 
      split line into data columns 
      # stay in (processing data) 
    save current table if any 
    # transition to (final state) 

Создание этого немного больше вещий:

tables = [] 
with open(filename) as file: 
    line = file.readline() 
    start_date, end_date = line[17:27], line[31:41] 
    table_name, table_rows = "", [] # pretend we start with a blank table 
    for line in file:    # reads lines one at a time until the end 
     line = line.strip()  # remove linefeed from end of line 
     if not line:    # check for blank line 
      continue 
     if line.endswith(';'*11): # line ends with 11 semicolons 
      # save the existing table; the first table will be blank 
      tables.append((table_name, table_rows)) 
      table_name = line[:-11] # name is all but the last 11 semicolons 
      table_rows = [] 
     else: 
      fields = line.split(';') 
      table_rows.append(fields) 
    # save the current table 
    table.append((table_name, table_rows)) 

Теперь вы должны иметь список таблиц (некоторые из них могут быть пустыми).

# maybe record start_date, end_date 
# process each table 
for table_name, table_rows in tables: 
    if not table_rows: # table is blank 
     continue 

    fields = table_rows[0] 
    if table_rows[-1][0] == "Total": 
     rows = table_rows[1:-1] 
     summary = table_rows[-1] 
    else: 
     rows = table_rows[1:] 
     summary = None 
    save_table(table_name, fields, rows, summary) 

Этот синтаксический анализатор прост, и мы сделали несколько ярлыков, чтобы сделать его еще проще.

Если язык был немного более сложным, мы бы оставили его в более абстрактной форме:

state = 0 
for line in file: 
    if state == 0: 
     if line matches transition from 0 to 0: 
      state = 0 
      save line data for state 0 
     elif line matches transition from 0 to 1: 
      state = 1 
      save line data for state 1 
     elif line matches transition from 0 to 2: 
      ... 
    elif state == 1: 
     if line matches transition from 1 to 0: 
      state = 0 
      save line data for state 0 
     elif line matches transition from 1 to 1: 
      state = 1 
      save line data for state 1 
     elif line matches transition from 1 to 2: 
      ... 
    elif state == 2: 
     ... 

идеи в этой должности будет охватывать большую часть данных, которые необходимо обработать.

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

+0

Привет Неаполитанский, Тхак вас за ответ – Brice

0

Спасибо за Ваш ответ

Я написал: ` строки = [] с открытым (путь + "CaParArticle.csv"), как TT: содержание = [line.strip() для линии в tt.readlines()]

import re 
re.findall("Date..",content[3]) 

idx_date=[i for i, item in enumerate(content) if re.search('Date', item)] 
idx_total=[i for i, item in enumerate(content) if re.search('Total [^H^T]|TOTAL [^H^T]', item)] 
tab={} 
tit={} 
for i in range(len(idx_date)): 
tab[i]=pd.DataFrame([ sub.split(";") for sub in content[idx_date[i]+1:idx_total[i]] ], \ 
     columns=content[idx_date[i]].split(";") ) 
    tit[i]=content[idx_total[i]][6: content[idx_total[i]].index(";")-1 ]\ 
     .replace('des ','').upper().replace(' ','_') 

tab={ tit[key]: value for key,value in tab.items() } 

`

+0

вы столкнетесь с проблемами, если поле происходит содержать«Дата»(например, если Клиент«Make AДатировка службы знакомств. Разделение на разделителе таблиц кажется гораздо более безопасным. – Neapolitan

+0

'для date_i, total_i в zip (idx_date, idx_total)' сделает ваш код немного более чистым. Вам не нужно 'i', так как вы можете назначить' title', поскольку вы назначили 'tit [i]', а затем назначьте 'tab [title]', поскольку вы назначили 'tab [i]'; это также удаляет перестановку словаря после цикла. – Neapolitan

 Смежные вопросы

  • Нет связанных вопросов^_^