#python #excel
#python #excel
Вопрос:
Я пытаюсь написать скрипт на Python для извлечения данных Wi-Fi из файла txt в csv
Вот данные txt:
Wed Oct 7 09:00:01 UTC 2020
BSS 02:ca:fe:ca:ca:40(on ap0_1)
freq: 2422
capability: IBSS (0x0012)
signal: -60.00 dBm
primary channel: 3
last seen: 30 ms ago
BSS ac:86:74:0a:73:a8(on ap0_1)
TSF: 229102338752 usec (2d, 15:38:22)
freq: 2422
capability: ESS (0x0421)
signal: -62.00 dBm
primary channel: 3
Мне нужно извлечь данные txt в файл csv в этом формате:
Time | BSS | freq |capability |signal| primary channel |
---------------------------- --------------------------- ------ ------------- ------ -----------------
Wed Oct 7 09:00:01 UTC 2020|02:ca:fe:ca:ca:40(on ap0_1)| 2422 |IBSS (0x0012)|-60.00| 3 |
|ac:86:74:0a:73:a8(on ap0_1)| 2422 |IBSS (0x0012)|-62.00| 3 |
Это мой незаконченный код:
import csv
import re
fieldnames = ['TIME', 'BSS', 'FREQ','CAPABILITY', 'SIGNAL', 'CHANNEL']
re_fields = re.compile(r'({}) :s(.*)'.format('|'.join(fieldnames)), re.I)
with open('ap0_1.txt') as f_input, open('ap0_1.csv', 'w', newline='') as f_output:
csv_output = csv.DictWriter(f_output, fieldnames= fieldnames)
csv_output.writeheader()
start = False
for line in f_input:
line = line.strip()
if len(line):
if 'BSS' in line:
if start:
start = False
block.append(line)
text_block = 'n'.join(block)
for field, value in re_fields.findall(text_block):
entry[field.upper()] = value
if line[0] == 'on ap0_1':
entry['BSS'] = block[0]
csv_output.writerow(entry)
else:
start = True
entry = {}
block = [line]
elif start:
block.append(line)
Когда я его запускаю, данные размещаются неправильно.
Пожалуйста, дайте мне знать, как это исправить. Я всего лишь новичок в программировании и был бы признателен за любой совет. Спасибо.
Комментарии:
1. Пожалуйста, добавьте желаемый и наблюдаемый результат для входных образцов к вашему вопросу.
2. Привет, Клаус Д. Я добавил желаемый результат.
3. Вопрос сбивает с толку. Вы говорите «вот данные», и вы также говорите «данные в этом формате», и эти два примера сильно отличаются. Как на самом деле выглядят входные данные?
4. Привет, Джон Гордон, извините, что сбил вас с толку. я отредактировал вопрос
Ответ №1:
Использование str.startswith
Пример:
import csv
fieldnames = ('TIME', 'BSS', 'freq','capability', 'signal', 'primary channel')
with open(filename) as f_input, open(outfile,'w', newline='') as f_output:
csv_output = csv.DictWriter(f_output, fieldnames= fieldnames)
csv_output.writeheader()
result = {"TIME": next(f_input).strip()} #Get Time, First Line
for line in f_input:
line = line.strip()
if line.startswith(fieldnames):
if line.startswith('BSS'):
key, value = line.split(" ", 1)
else:
key, value = line.split(": ")
result[key] = value
csv_output.writerow(result)
РЕДАКТИРОВАТЬ согласно комментарию
Если у вас есть несколько блоков приведенного выше текста
import re
import csv
week_ptrn = re.compile(r"b(" "|".join(('Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat', 'Sun')) r")b")
fieldnames = ('TIME', 'BSS', 'freq','capability', 'signal', 'primary channel')
with open(filename) as f_input, open(outfile,'w', newline='') as f_output:
csv_output = csv.DictWriter(f_output, fieldnames= fieldnames)
csv_output.writeheader()
result = [] #Get Time, First Line
for line in f_input:
line = line.strip()
week = week_ptrn.match(line)
if week:
result.append({"TIME": line})
if line.startswith(fieldnames):
if line.startswith('BSS'):
key, value = line.split(" ", 1)
else:
key, value = line.split(": ")
result[-1][key] = value
csv_output.writerows(result)
Комментарии:
1. Привет, Ракеш, код извлекает только 1-й BSS, но не 2-й BSS
2. Извините, я не понимаю… У вас есть несколько блоков приведенной выше строки в текстовом файле?
3. Да, каждый блок начинается с BSS и заканчивается основным каналом
Ответ №2:
Вы пытались выполнить поиск времени с помощью «TIME». Но во входных данных нет «ВРЕМЕНИ». Таким образом, вывод с пустым временем является естественным.
И я думаю, что следующие строки также имеют проблему.
if line[0] == 'on ap0_1':
entry['BSS'] = block[0]
По-моему, вы пытались найти on ap0_1
of BSS ac:86:74:0a:73:a8(on ap0_1)
.
Но строка [0] — это ‘BSS’, первая из [‘BSS’, ‘ac:86:74:0a:73:a8(on’, ‘ap0_1)’] . Это должно измениться следующим образом:
if 'on ap0_1' in block[0]:
entry['BSS'] = block[0][4:].lstrip()
Ответ №3:
Вот моя версия кода.
import csv, re
fieldnames = ['TIME', 'BSS', 'FREQ','CAPABILITY', 'SIGNAL', 'CHANNEL']
re_fields = re.compile(r'({}) :s(.*)'.format('|'.join(fieldnames)), re.I)
with open('ap0_1.txt') as f_input, open('ap0_1.csv', 'w', newline='') as f_output:
csv_output = csv.DictWriter(f_output, fieldnames= fieldnames)
csv_output.writeheader()
start = False
time_condition = lambda @l: l.startswith('Mon') or l.startswith('Tue') or
l.startswith('Wed') or l.startswith('Thu') or l.startswith('Fri')
or l.startswith('Sat') or l.startswith('Sun')
row = dict{}
for line in f_input:
line = line.strip()
if not line:
continue
elif time_condition(line):
row['TIME'] = line
else:
# not sure how you define the start of a new block, say, it is by 'BSS' string
key, value = line.split(' ', 1) # split one time exactly
key = key.rstrip(':').upper()
if key == 'BSS' and row:
row = (row.get(k, '') for k in fieldnames)
csv_output.writerow(row)
row = dict()
row[key.upper()] = value
row = (row.get(k, '') for k in fieldnames)
csv_output.writerow(row)
Похоже, что ‘ n’ создает пустые строки.
Комментарии:
1. Привет @kate-melnykova, когда я попытался запустить код, он сказал, что block [‘TIME’] = строка не определена.