Работа с именованными кортежами для вывода определенных данных

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

Это мой код до сих пор:

from kafka import KafkaConsumer
import ast
from collections import namedtuple
import json
import csv
import sys
from datetime import datetime
import os

# connect to kafka topic
kaf = KafkaConsumer('kafka.topic',
                   auto_offset_reset='earliest', bootstrap_servers=['consumer-kafka.server'])
outputfile = 'C:\\Users\\Documents\\KafkaConsum\\file.csv'

outfile = open(outputfile, mode='w', newline='')

for row in kaf:
    a = row.value.decode("utf-8")
        if "TAG_NAME" in a:
            print(a)
            outfile.write(a + '\n')

Вот как мои данные отформатированы:

2018-12-04 13:27:12,511 [a-1 app=helloname,receiverId=abc-abc-123-123,partner=company] INFO kafka.consumer.topic TAG_NAME Type='Generic App' Class= UpdateCheck description= Версия 1 appName=TWITTER appAction=start

2018-12-04 13:27:12,511 [a-1 app=helloname,receiverId=abc-abc-123-123,partner=company] INFO kafka.consumer.topic TAG_NAME Type='Generic App' Class= UpdateCheck description= Версия 1 appName=TWITTER appAction=start

Я хочу иметь возможность анализировать эти данные, чтобы они выглядели так в моем CSV-файле:

приложение | идентификатор получателя | партнер | Тип | Класс | описание | имя_приложения | приложениеДействие |

приветимя | абв-абв-123-123 | компания | Общее приложение | Проверка обновлений | Версия1 | Твиттер | начать |

приветимя | абв-абв-123-123 | компания | Общее приложение | Проверка обновлений | Версия1 | Твиттер | начать |


person j.Doe    schedule 07.12.2018    source источник
comment
Вы можете использовать регулярное выражение для извлечения данных из каждой строки (пример заголовка stackoverflow.com/questions/30627810/)   -  person Mohamed Ali JAMAOUI    schedule 07.12.2018


Ответы (2)


Вот решение, но оно не использует csv (вероятно, должно).

Он захватывает заголовок и значение в findall(..., а затем, ниже, отделяет заголовок от значения (разделенного знаком =) и записывает заголовок (только один раз) и все значения.

import re

def main():
    header = True
    fin = open('f3.txt', 'r')
    for line in fin:
        data = re.findall(r'\w+=\s*[\'"]?[\w-]+', line)
        headers = []
        array = []
        for pair in data:
            m = re.search(r'(\w+)=\s*[\'"]?([\w-]+)', pair)
            headers.append(m.group(1)) # get header
            array.append(m.group(2))   # get value

        if header == True:
            print('|'.join(headers))
            header = False
        print('|'.join(array))
    fin.close()

main()

Это произвело этот вывод:

app|receiverId|partner|Type|Class|description|appName|appAction
helloname|abc-abc-123-123|company|Generic|UpdateCheck|Version1|TWITTER|start
helloname|abc-abc-123-123|company|Generic|UpdateCheck|Version1|TWITTER|start
person Chris Charley    schedule 07.12.2018

Как сказал Медали, вы можете использовать регулярное выражение для получения нужных данных и правильного их разделения. Что-то вроде;

import re

pattern = r'app=(.*?),'
app = re.search(pattern, a).group(1)

на самом деле у вас может быть список тех заголовков, которые вы хотите, и сделать цикл for по шаблону, сохранив его в словаре, а затем записать это непосредственно в csv.

вам понадобится новая переменная csv_outfile или что-то подобное и измените свои открытые переменные;

headers = ['app', 'receiverid', .... , 'appAction']
outfile = open(outputfile, mode='wb')
csv_outfile = csv.DictWriter(outfile, headers, delimiter = '|')
csv_outfile.writeheader()


for header in headers:
    pattern = header + r'=(.*?),'
    my_dict[header] = re.search(pattern, a).group(1)
csv_outfile.writerow(my_dict)

Я думаю, это отвечает на ваши вопросы?

person SRT HellKitty    schedule 07.12.2018
comment
Я пытался использовать это, но продолжаю получать ошибки AttributeError: объект «NoneType» не имеет атрибута «группа» и TypeError: нехешируемый тип: «список». Я сделал несколько изменений, таких как добавление my_dict = {} и my_dict[headers] = re.search(pattern, str(a)).group(1) - person j.Doe; 10.12.2018
comment
AttributeError: 'NoneType' object has no attribute 'group' означает, что вы не получаете результатов поиска, убедитесь, что заголовок правильный. Вы знаете, откуда TypeError: unhashable type: 'list'. в коде? - person SRT HellKitty; 10.12.2018